home *** CD-ROM | disk | FTP | other *** search
- From: lee@sq.sq.com (Liam R. E. Quin)
- Newsgroups: alt.sources
- Subject: lq-text Full Text Retrieval Database Part 11/13
- Message-ID: <1991Mar4.021055.16938@sq.sq.com>
- Date: 4 Mar 91 02:10:55 GMT
-
- : cut here --- cut here --
- : To unbundle, sh this file
- #! /bin/sh
- : part 11
- echo x - lq-text/src/test/trywid.c 1>&2
- sed 's/^X//' >lq-text/src/test/trywid.c <<'@@@End of lq-text/src/test/trywid.c'
- X/* trywid.c -- Copyright 1989 Liam R. Quin. All Rights Reserved.
- X * This code is NOT in the public domain.
- X * See the file COPYRIGHT for full details.
- X *
- X * $Header: /usr/src/cmd/lq-text/src/test/RCS/trywid.c,v 1.1 90/08/09 19:17:51 lee Rel1-10 $
- X *
- X * $Log: trywid.c,v $
- X * Revision 1.1 90/08/09 19:17:51 lee
- X * Initial revision
- X *
- X *
- X */
- X
- X#include "globals.h" /* defines and declarations for database filenames */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include "fileinfo.h"
- X#include "wordinfo.h"
- X
- X/** Unix Library Functions: **/
- Xextern long atol();
- X/** liblqtext functions: **/
- Xextern t_WID GetMaxWID();
- Xextern t_WID GetNextWID();
- X/** **/
- X
- Xint
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X t_WID W, Max;
- X
- X Max = atol(argv[1]);
- X
- X for (W = GetMaxWID(); W <= Max; ) {
- X printf("%lu\n", W = GetNextWID());
- X }
- X return 0;
- X}
- @@@End of lq-text/src/test/trywid.c
- echo x - lq-text/src/test/wordlengths 1>&2
- sed 's/^X//' >lq-text/src/test/wordlengths <<'@@@End of lq-text/src/test/wordlengths'
- XA
- XBB
- XCCC
- XDDDD
- XEEEEE
- XFFFFFF
- XGGGGGGG
- XHHHHHHHH
- XIIIIIIIII
- XJJJJJJJJJJ
- XKKKKKKKKKKK
- XLLLLLLLLLLLL
- XMMMMMMMMMMMMM
- XNNNNNNNNNNNNNN
- XOOOOOOOOOOOOOOO
- XPPPPPPPPPPPPPPPP
- XQQQQQQQQQQQQQQQQQ
- XRRRRRRRRRRRRRRRRRR
- XSSSSSSSSSSSSSSSSSSS
- XTTTTTTTTTTTTTTTTTTTT
- XUUUUUUUUUUUUUUUUUUUUU
- XVVVVVVVVVVVVVVVVVVVVVV
- XWWWWWWWWWWWWWWWWWWWWWWW
- XXXXXXXXXXXXXXXXXXXXXXXXX
- XYYYYYYYYYYYYYYYYYYYYYYYYY
- XZZZZZZZZZZZZZZZZZZZZZZZZZZ
- X
- XA
- XBB
- XCCC
- XDDDD
- XEEEEE
- XFFFFFF
- XGGGGGGG
- XHHHHHHHH
- XIIIIIIIII
- XJJJJJJJJJJ
- XKKKKKKKKKKK
- XLLLLLLLLLLLL
- XMMMMMMMMMMMMM
- XNNNNNNNNNNNNNN
- XOOOOOOOOOOOOOOO
- XPPPPPPPPPPPPPPPP
- XQQQQQQQQQQQQQQQQQ
- XRRRRRRRRRRRRRRRRRR
- XSSSSSSSSSSSSSSSSSSS
- XTTTTTTTTTTTTTTTTTTTT
- XUUUUUUUUUUUUUUUUUUUUU
- XVVVVVVVVVVVVVVVVVVVVVV
- XWWWWWWWWWWWWWWWWWWWWWWW
- XXXXXXXXXXXXXXXXXXXXXXXXX
- XYYYYYYYYYYYYYYYYYYYYYYYYY
- XZZZZZZZZZZZZZZZZZZZZZZZZZZ
- X
- @@@End of lq-text/src/test/wordlengths
- echo x - lq-text/src/ozmahash/Makefile 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/Makefile <<'@@@End of lq-text/src/ozmahash/Makefile'
- X# $Id: Makefile,v 1.2 91/03/02 19:10:36 lee Exp $
- XDIR= .
- XSRC1= dynahash.c log2.c page.c big.c buf.c hfunc.c
- XSRC2= mkstemp.c bcopy.c
- XSRCS= $(SRC1) $(SRC2)
- X#SRCS= $(SRC1)
- XOBJ1= dynahash.o log2.o page.o big.o buf.o hfunc.o
- XOBJ2= mkstemp.o bcopy.o
- XOBJS= $(OBJ1) $(OBJ2)
- X#OBJS= $(OBJ1)
- XMAIN1= tread2.c tverify.c tseq.c tdel.c thash4.c tcreat3.c
- XMAINS= thash.c tcreat.c tread.c tread2.c tverify.c tseq.c tseq2.c tcreat2.c thash2.c tdel.c thash3.c thash4.c tcreat3.c
- XHDRS= hash.h page.h db.h endian.h
- XRANLIB=ranlib
- X
- XDEBUGFLAGS= -DHASH_STATISTICS -g -pg
- XPROFFLAGS= -p -DHASH_STATISTICS
- XTIMEFLAGS = -O2
- XTESTFLAGS= $(DEBUGFLAGS)
- XLDFLAGS=
- X#CFLAGS= -I. $(DEBUGFLAGS)
- X#CFLAGS= -I. $(PROFFLAGS)
- XCFLAGS= -I. $(TIMEFLAGS)
- X
- Xall: install
- X $(MAKE) -$(MAKEFLAGS) tidy
- X
- X#all: libhash.a tread2 tverify tseq thash4 tcreat3 tdel
- X#all: tcreat tread tread2 tverify thash tseq tseq2 tcreat2 thash2 thash3 thash4 tdel tcreat3
- X
- Xlib: libhash.a
- X
- Xinstall: lib
- X cp libhash.a ../lib
- X $(RANLIB) ../lib/libhash.a
- X
- Xtidy:
- X /bin/rm -f *.o core *.out
- X
- Xclean: tidy
- X /bin/rm -f core *.a
- X
- Xtar:
- X tar cf hash.tar README Makefile $(SRCS) $(MAIN1) $(HDRS) ndbm.c ndbm.h hsearch.c search.h byte_order.c db.3 hash.ps
- X
- Xshar:
- X shar -f XFER $(SRC1) $(MAINS) $(HDRS) Makefile
- X
- Xlibhash.a: $(OBJS) ndbm.o hsearch.o
- X ar ruv libhash.a $(OBJS) ndbm.o hsearch.o
- X $(RANLIB) libhash.a
- X
- Xtdel: tdel.o $(OBJS)
- X cc tdel.o $(LDFLAGS) -o tdel $(OBJS)
- X
- Xtseq2: tseq2.o $(OBJS)
- X cc tseq2.o $(LDFLAGS) -o tseq2 $(OBJS)
- X
- Xtseq: tseq.o $(OBJS)
- X cc tseq.o $(LDFLAGS) -o tseq $(OBJS)
- X
- Xtverify: tverify.o $(OBJS)
- X cc tverify.o $(LDFLAGS) -o tverify $(OBJS)
- X
- Xtcreat2: tcreat2.o $(OBJS)
- X cc tcreat2.o $(LDFLAGS) -o tcreat2 $(OBJS)
- X
- Xtcreat3: tcreat3.o $(OBJS)
- X cc tcreat3.o $(LDFLAGS) -o tcreat3 $(OBJS)
- X
- Xtcreat: tcreat.o $(OBJS)
- X cc tcreat.o $(LDFLAGS) -o tcreat $(OBJS)
- X
- Xtread: tread.o $(OBJS)
- X cc tread.o $(LDFLAGS) -o tread $(OBJS)
- X
- Xtread2: tread2.o $(OBJS)
- X cc tread2.o $(LDFLAGS) -o tread2 $(OBJS)
- X
- Xthash: thash.o $(OBJS)
- X cc thash.o $(LDFLAGS) -o thash $(OBJS)
- X
- Xthash2: thash2.o $(OBJS)
- X cc thash2.o $(LDFLAGS) -o thash2 $(OBJS)
- X
- Xthash3: thash3.o $(OBJS)
- X cc thash3.o $(LDFLAGS) -o thash3 $(OBJS)
- X
- Xthash4: thash4.o $(OBJS)
- X cc thash4.o $(LDFLAGS) -o thash4 $(OBJS)
- X
- X
- Xsrc:
- X co $(SRCS) $(HDRS) $(MAINS)
- X
- Xdepend:
- X mkdep $(CFLAGS) $(SRCS)
- X
- X# DO NOT DELETE THIS LINE -- mkdep uses it.
- X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
- X
- Xdynahash.o: dynahash.c db.h hash.h endian.h
- Xlog2.o: log2.c
- Xpage.o: page.c db.h hash.h page.h endian.h
- Xbig.o: big.c db.h hash.h page.h
- Xbuf.o: buf.c hash.h
- Xhfunc.o: hfunc.c
- Xmkstemp.o: mkstemp.c
- Xbcopy.o: bcopy.c
- X
- X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
- @@@End of lq-text/src/ozmahash/Makefile
- echo x - lq-text/src/ozmahash/README 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/README <<'@@@End of lq-text/src/ozmahash/README'
- XThis package implements a superset of the hsearch and dbm/ndbm libraries.
- X
- XContents:
- X
- XHashing Package:
- X dynahash.c
- X page.c
- X buf.c
- X big.c
- X hfunc.c
- X log2.c
- X
- X hash.h
- X page.h
- X db.h
- X
- XBackward Compatibility Routines:
- X ndbm.c
- X ndbm.h
- X hsearch.c
- X search.h
- X
- XMisc
- X byte_order.c
- X
- XBSD Files:
- X endian.h
- X mkstemp.c
- X bcopy.c
- X
- XTest Programs:
- X All test programs which need key/data pairs expect them entered
- X with key and data on separate lines
- X
- X tcreat3.c
- X Takes
- X bucketsize (bsize),
- X fill factor (ffactor), and
- X initial number of elements (nelem).
- X Creates a hash table named hashtest containing the
- X keys/data pairs entered from standard in.
- X thash4.c
- X Takes
- X bucketsize (bsize),
- X fill factor (ffactor),
- X initial number of elements (nelem)
- X bytes of cache (ncached), and
- X file from which to read data (fname)
- X Creates a table from the key/data pairs on standard in and
- X then does a read of each key/data in fname
- X tdel.c
- X Takes
- X bucketsize (bsize), and
- X fill factor (ffactor).
- X file from which to read data (fname)
- X Reads each key/data pair from fname and deletes the
- X key from the hash table hashtest
- X tseq.c
- X Reads the key/data pairs in the file hashtest and writes them
- X to standard out.
- X tread2.c
- X Takes
- X butes of cache (ncached).
- X Reads key/data pairs from standard in and looks them up
- X in the file hashtest.
- X tverify.c
- X Reads key/data pairs from standard in, looks them up
- X in the file hashtest, and verifies that the data is
- X correct.
- X
- XIf you are running on a BSD system, the BSD h files should be in
- X/usr/include and the BSD .c files should be in libc. On a non-BSD
- Xsystem, you will need to compile the copies here into the package.
- XBe sure to set BYTE_ORDER in endian.h appropriately for your machine.
- XIf you don't know what "endian" your machine is, compile byte_order.c
- Xand run it. It should tell you.
- X
- XThe file search.h is used only for using the hsearch compatible interface on
- XBSD systems. On System V derived systems, search.h should appear in
- X/usr/include.
- X
- XThe man page db.3 explains the interface to the hashing system.
- XThe file hash.ps is a postscript copy of a paper explaining
- Xthe history, implementation, and performance of the hash package.
- X
- X"bugs" or idiosyncracies
- X
- XIf you have a lot of overflows, it is possible to run out of overflow
- Xpages. Currently, this will cause a message to be printed on stderr.
- XEventually, this will be indicated by a return error code.
- X
- XIf you have a lot of overflow pages and a small cache, you might run
- Xout of buffers to hold a single hash chain. You will get an error
- Xexit. If you have very long keys and/or small pages, try increasing
- Xyour buffer pool space to make this go away (you can also compile
- Xwith HASH_STATISTICS to see just how many expansions you really are
- Xgetting).
- @@@End of lq-text/src/ozmahash/README
- echo x - lq-text/src/ozmahash/bcopy.c 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/bcopy.c <<'@@@End of lq-text/src/ozmahash/bcopy.c'
- X/*-
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Chris Torek.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that: (1) source distributions retain this entire copyright
- X * notice and comment, and (2) distributions including binaries display
- X * the following acknowledgement: ``This product includes software
- X * developed by the University of California, Berkeley and its contributors''
- X * in the documentation or other materials provided with the distribution
- X * and in all advertising materials mentioning features or use of this
- X * software. Neither the name of the University nor the names of its
- X * contributors may be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "@(#)bcopy.c 5.7 (Berkeley) 5/16/90";
- X#endif /* LIBC_SCCS and not lint */
- X
- X#include <string.h>
- X#include <sys/types.h>
- X
- X/*
- X * sizeof(word) MUST BE A POWER OF TWO
- X * SO THAT wmask BELOW IS ALL ONES
- X */
- Xtypedef int word; /* "word" used for optimal copy speed */
- X
- X#define wsize sizeof(word)
- X#define wmask (wsize - 1)
- X
- X/*
- X * Copy a block of memory, handling overlap.
- X * This is the routine that actually implements
- X * (the portable versions of) bcopy, memcpy, and memmove.
- X */
- Xvoid
- Xbcopy(src0, dst0, length)
- X char *dst0;
- X char *src0;
- X register size_t length;
- X{
- X register char *dst = dst0;
- X register char *src = src0;
- X register size_t t;
- X
- X if (length == 0 || dst == src) /* nothing to do */
- X return;
- X
- X /*
- X * Macros: loop-t-times; and loop-t-times, t>0
- X */
- X#define TLOOP(s) if (t) TLOOP1(s)
- X#define TLOOP1(s) do { s; } while (--t)
- X
- X if ((unsigned long)dst < (unsigned long)src) {
- X /*
- X * Copy forward.
- X */
- X t = (int)src; /* only need low bits */
- X if ((t | (int)dst) & wmask) {
- X /*
- X * Try to align operands. This cannot be done
- X * unless the low bits match.
- X */
- X if ((t ^ (int)dst) & wmask || length < wsize)
- X t = length;
- X else
- X t = wsize - (t & wmask);
- X length -= t;
- X TLOOP1(*dst++ = *src++);
- X }
- X /*
- X * Copy whole words, then mop up any trailing bytes.
- X */
- X t = length / wsize;
- X TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
- X t = length & wmask;
- X TLOOP(*dst++ = *src++);
- X } else {
- X /*
- X * Copy backwards. Otherwise essentially the same.
- X * Alignment works as before, except that it takes
- X * (t&wmask) bytes to align, not wsize-(t&wmask).
- X */
- X src += length;
- X dst += length;
- X t = (int)src;
- X if ((t | (int)dst) & wmask) {
- X if ((t ^ (int)dst) & wmask || length <= wsize)
- X t = length;
- X else
- X t &= wmask;
- X length -= t;
- X TLOOP1(*--dst = *--src);
- X }
- X t = length / wsize;
- X TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
- X t = length & wmask;
- X TLOOP(*--dst = *--src);
- X }
- X return;
- X}
- @@@End of lq-text/src/ozmahash/bcopy.c
- echo x - lq-text/src/ozmahash/big.c 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/big.c <<'@@@End of lq-text/src/ozmahash/big.c'
- X/*-
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Margo Seltzer.
- X *
- X * %sccs.include.redist.c%
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "%W% (Berkeley) %G%";
- X#endif /* LIBC_SCCS and not lint */
- X
- X/******************************************************************************
- X
- XPACKAGE: hash
- X
- XDESCRIPTION:
- X Big key/data handling for the hashing package.
- X
- XROUTINES:
- X External
- X big_keydata
- X big_split
- X big_insert
- X big_return
- X big_delete
- X find_last_page
- X Internal
- X collect_key
- X collect_data
- X******************************************************************************/
- X/* Includes */
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <assert.h>
- X#include <errno.h>
- X#include <db.h>
- X#include <hash.h>
- X#include <page.h>
- X#include <stdio.h>
- X
- X/* Externals */
- X/* buf.c */
- Xextern BUFHEAD *get_buf();
- X
- X/* page.c */
- Xextern BUFHEAD *add_ovflpage();
- X
- X/* My externals */
- Xextern int big_keydata();
- Xextern int big_split();
- Xextern int big_insert();
- Xextern int big_return();
- Xextern int big_delete();
- Xextern u_short find_last_page();
- Xextern int find_bigpair();
- X
- X/* My internals */
- Xstatic int collect_key();
- Xstatic int collect_data();
- X
- X#ifdef HASH_STATISTICS
- Xextern long hash_accesses, hash_collisions, hash_expansions, hash_overflows;
- X#endif
- X/*
- XBig_insert
- X
- XYou need to do an insert and the key/data pair is too big
- X0 ==> OK
- X-1 ==> ERROR
- X*/
- Xextern int
- Xbig_insert ( bufp, key, val )
- XBUFHEAD *bufp;
- XDBT *key, *val;
- X{
- X char *cp = bufp->page; /* Character pointer of p */
- X register u_short *p = (u_short *)cp;
- X char *key_data, *val_data;
- X int key_size, val_size;
- X int n;
- X u_short space, move_bytes, off;
- X
- X key_data = key->data;
- X key_size = key->size;
- X val_data = val->data;
- X val_size = val->size;
- X
- X /* First move the Key */
- X for ( space = FREESPACE(p) - BIGOVERHEAD;
- X key_size;
- X space = FREESPACE(p) - BIGOVERHEAD ) {
- X move_bytes = MIN(space, key_size);
- X off = OFFSET(p) - move_bytes;
- X bcopy (key_data, cp+off, move_bytes );
- X key_size -= move_bytes;
- X key_data += move_bytes;
- X n = p[0];
- X p[++n] = off;
- X p[0] = ++n;
- X FREESPACE(p) = off - PAGE_META(n);
- X OFFSET(p) = off;
- X p[n] = PARTIAL_KEY;
- X bufp = add_ovflpage(bufp);
- X if ( !bufp ) {
- X return(-1);
- X }
- X n = p[0];
- X if ( !key_size ) {
- X if ( FREESPACE(p) ) {
- X move_bytes = MIN (FREESPACE(p), val_size);
- X off = OFFSET(p) - move_bytes;
- X p[n] = off;
- X bcopy ( val_data, cp + off, move_bytes );
- X val_data += move_bytes;
- X val_size -= move_bytes;
- X p[n-2] = FULL_KEY_DATA;
- X FREESPACE(p) = FREESPACE(p) - move_bytes;
- X OFFSET(p) = off;
- X }
- X else p[n-2] = FULL_KEY;
- X }
- X p = (u_short *)bufp->page;
- X cp = bufp->page;
- X bufp->flags |= BUF_MOD;
- X }
- X
- X /* Now move the data */
- X for ( space = FREESPACE(p) - BIGOVERHEAD;
- X val_size;
- X space = FREESPACE(p) - BIGOVERHEAD ) {
- X move_bytes = MIN(space, val_size);
- X /*
- X Here's the hack to make sure that if the data ends
- X on the same page as the key ends, FREESPACE is
- X at least one
- X */
- X if ( space == val_size && val_size == val->size ) {
- X move_bytes--;
- X }
- X off = OFFSET(p) - move_bytes;
- X bcopy (val_data, cp+off, move_bytes );
- X val_size -= move_bytes;
- X val_data += move_bytes;
- X n = p[0];
- X p[++n] = off;
- X p[0] = ++n;
- X FREESPACE(p) = off - PAGE_META(n);
- X OFFSET(p) = off;
- X if ( val_size ) {
- X p[n] = FULL_KEY;
- X bufp = add_ovflpage (bufp);
- X if ( !bufp ) {
- X return(-1);
- X }
- X cp = bufp->page;
- X p = (u_short *)cp;
- X } else {
- X p[n] = FULL_KEY_DATA;
- X }
- X bufp->flags |= BUF_MOD;
- X }
- X return(0);
- X}
- X
- X/*
- X Called when bufp's page contains a partial key (index should be 1)
- X
- X All pages in the big key/data pair except bufp are freed. We cannot
- X free bufp because the page pointing to it is lost and we can't
- X get rid of its pointer.
- X
- X Returns 0 => OK
- X -1 => ERROR
- X*/
- Xextern int
- Xbig_delete (bufp, ndx)
- XBUFHEAD *bufp;
- Xint ndx;
- X{
- X register BUFHEAD *rbufp = bufp;
- X register BUFHEAD *last_bfp = NULL;
- X char *cp;
- X u_short *bp = (u_short *)bufp->page;
- X u_short *xbp;
- X u_short pageno = 0;
- X u_short off, free_sp;
- X int key_done = 0;
- X int n;
- X
- X while (!key_done || (bp[2] != FULL_KEY_DATA)) {
- X if ( bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA ) key_done = 1;
- X
- X /*
- X If there is freespace left on a FULL_KEY_DATA page,
- X then the data is short and fits entirely on this
- X page, and this is the last page.
- X */
- X if ( bp[2] == FULL_KEY_DATA && FREESPACE(bp) ) break;
- X pageno = bp[bp[0]-1];
- X rbufp->flags |= BUF_MOD;
- X rbufp = get_buf ( pageno, rbufp, 0 );
- X if ( last_bfp ) free_ovflpage(last_bfp);
- X last_bfp = rbufp;
- X if ( !rbufp ) return(-1); /* Error */
- X bp = (u_short *)rbufp->page;
- X }
- X
- X /*
- X If we get here then rbufp points to the last page of
- X the big key/data pair. Bufp points to the first
- X one -- it should now be empty pointing to the next
- X page after this pair. Can't free it because we don't
- X have the page pointing to it.
- X */
- X
- X /* This is information from the last page of the pair */
- X n = bp[0];
- X pageno = bp[n-1];
- X
- X /* Now, bp is the first page of the pair */
- X bp = (u_short *)bufp->page;
- X if ( n > 2 ) {
- X /* There is an overflow page */
- X bp[1] = pageno;
- X bp[2] = OVFLPAGE;
- X bufp->ovfl = rbufp->ovfl;
- X } else {
- X /* This is the last page */
- X bufp->ovfl = NULL;
- X }
- X n -= 2;
- X bp[0] = n;
- X FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- X OFFSET(bp) = hashp->BSIZE - 1;
- X
- X bufp->flags |= BUF_MOD;
- X if ( rbufp ) free_ovflpage(rbufp);
- X if ( last_bfp != rbufp ) free_ovflpage(last_bfp);
- X
- X hashp->NKEYS--;
- X return(0);
- X}
- X
- X/*
- X 0 = key not found
- X -1 = get next overflow page
- X -2 means key not found and this is big key/data
- X -3 error
- X*/
- Xextern int
- Xfind_bigpair(bufp, ndx, key, size )
- XBUFHEAD *bufp;
- Xint ndx;
- Xchar *key;
- Xint size;
- X{
- X register u_short *bp = (u_short *)bufp->page;
- X register char *p = bufp->page;
- X int ksize = size;
- X char *kkey = key;
- X u_short bytes;
- X
- X
- X for ( bytes = hashp->BSIZE - bp[ndx];
- X bytes <= size && bp[ndx+1] == PARTIAL_KEY;
- X bytes = hashp->BSIZE - bp[ndx] ) {
- X
- X if ( bcmp ( p+bp[ndx], kkey, bytes ))return(-2);
- X kkey += bytes;
- X ksize -= bytes;
- X bufp = get_buf ( bp[ndx+2], bufp, 0 );
- X if ( !bufp ) {
- X return(-3);
- X }
- X p = bufp->page;
- X bp = (u_short *)p;
- X ndx = 1;
- X }
- X
- X if ( (bytes != ksize) || bcmp ( p+bp[ndx], kkey, bytes )) {
- X#ifdef HASH_STATISTICS
- X hash_collisions++;
- X#endif
- X return(-2);
- X }
- X else return (ndx);
- X}
- X
- X
- X/*
- X Given the buffer pointer of the first overflow page of a big pair,
- X find the end of the big pair
- X
- X This will set bpp to the buffer header of the last page of the big pair.
- X It will return the pageno of the overflow page following the last page of
- X the pair; 0 if there isn't any (i.e. big pair is the last key in the
- X bucket)
- X*/
- Xextern u_short
- Xfind_last_page ( bpp )
- XBUFHEAD **bpp;
- X{
- X int n;
- X u_short pageno;
- X BUFHEAD *bufp = *bpp;
- X u_short *bp = (u_short *)bufp->page;
- X
- X while ( 1 ) {
- X n = bp[0];
- X
- X /*
- X This is the last page if:
- X the tag is FULL_KEY_DATA and either
- X only 2 entries
- X OVFLPAGE marker is explicit
- X there is freespace on the page
- X */
- X if ( bp[2] == FULL_KEY_DATA &&
- X ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)) ) ) break;
- X
- X pageno = bp[n-1];
- X bufp = get_buf ( pageno, bufp, 0 );
- X if ( !bufp ) return (0); /* Need to indicate an error! */
- X bp = (u_short *)bufp->page;
- X }
- X
- X *bpp = bufp;
- X if ( bp[0] > 2 ) return ( bp[3] );
- X else return(0);
- X}
- X
- X
- X/*
- X Return the data for the key/data pair
- X that begins on this page at this index
- X (index should always be 1)
- X*/
- Xextern int
- Xbig_return ( bufp, ndx, val, set_current )
- XBUFHEAD *bufp;
- Xint ndx;
- XDBT *val;
- Xint set_current;
- X{
- X BUFHEAD *save_p;
- X u_short save_addr;
- X u_short *bp = (u_short *)bufp->page;
- X u_short off, len;
- X char *cp, *tp;
- X
- X while ( bp[ndx+1] == PARTIAL_KEY ) {
- X bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if ( !bufp ) return(-1);
- X bp = (u_short *)bufp->page;
- X ndx = 1;
- X }
- X
- X if ( bp[ndx+1] == FULL_KEY ) {
- X bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if ( !bufp ) return(-1);
- X bp = (u_short *)bufp->page;
- X save_p = bufp;
- X save_addr = save_p->addr;
- X off = bp[1];
- X len = 0;
- X } else if (!FREESPACE(bp)) {
- X /*
- X This is a hack. We can't distinguish between
- X FULL_KEY_DATA that contains complete data or
- X incomplete data, so we require that if the
- X data is complete, there is at least 1 byte
- X of free space left.
- X */
- X off = bp[bp[0]];
- X len = bp[1] - off;
- X save_p = bufp;
- X save_addr = bufp->addr;
- X bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if ( !bufp ) return(-1);
- X bp = (u_short *)bufp->page;
- X } else {
- X /* The data is all on one page */
- X tp = (char *)bp;
- X off = bp[bp[0]];
- X val->data = tp + off;
- X val->size = bp[1] - off;
- X if ( set_current ) {
- X if ( bp[0] == 2 ) { /* No more buckets in chain */
- X hashp->cpage = NULL;
- X hashp->cbucket++;
- X hashp->cndx=1;
- X } else {
- X hashp->cpage = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if ( !hashp->cpage )return(-1);
- X hashp->cndx = 1;
- X if ( !((u_short *)hashp->cpage->page)[0] ) {
- X hashp->cbucket++;
- X hashp->cpage = NULL;
- X }
- X }
- X }
- X return(0);
- X }
- X
- X val->size = collect_data ( bufp, len, set_current );
- X if ( val->size == -1 ) {
- X return(-1);
- X }
- X if ( save_p->addr != save_addr ) {
- X /* We are pretty short on buffers */
- X errno = EINVAL; /* OUT OF BUFFERS */
- X return(-1);
- X }
- X bcopy ( (save_p->page)+off, hashp->tmp_buf, len );
- X val->data = hashp->tmp_buf;
- X return(0);
- X}
- X
- X/*
- X Count how big the total datasize is by
- X recursing through the pages. Then allocate
- X a buffer and copy the data as you recurse up.
- X*/
- Xstatic int
- Xcollect_data ( bufp, len, set )
- XBUFHEAD *bufp;
- Xint len;
- Xint set;
- X{
- X register char *p = bufp->page;
- X register u_short *bp = (u_short *)p;
- X u_short save_addr;
- X int mylen, totlen;
- X BUFHEAD *xbp;
- X
- X mylen = hashp->BSIZE - bp[1];
- X save_addr = bufp->addr;
- X
- X if ( bp[2] == FULL_KEY_DATA ) { /* End of Data */
- X totlen = len + mylen;
- X if ( hashp->tmp_buf ) free (hashp->tmp_buf);
- X hashp->tmp_buf = (char *)malloc ( totlen );
- X if ( !hashp->tmp_buf ) {
- X return(-1);
- X }
- X if ( set ) {
- X hashp->cndx = 1;
- X if ( bp[0] == 2 ) { /* No more buckets in chain */
- X hashp->cpage = NULL;
- X hashp->cbucket++;
- X } else {
- X hashp->cpage = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if (!hashp->cpage) {
- X return(-1);
- X } else if ( !((u_short *)hashp->cpage->page)[0] ) {
- X hashp->cbucket++;
- X hashp->cpage = NULL;
- X }
- X }
- X }
- X } else {
- X xbp = get_buf ( bp[bp[0]-1], bufp, 0 );
- X if ( !xbp || ((totlen = collect_data ( xbp, len + mylen, set )) < 1) ) {
- X return(-1);
- X }
- X }
- X if ( bufp->addr != save_addr ) {
- X errno = EINVAL; /* Out of buffers */
- X return(-1);
- X }
- X bcopy ( (bufp->page) + bp[1], &hashp->tmp_buf[len], mylen );
- X return ( totlen );
- X}
- X
- X/*
- X Fill in the key and data
- X for this big pair
- X*/
- Xextern int
- Xbig_keydata ( bufp, ndx, key, val, set )
- XBUFHEAD *bufp;
- Xint ndx;
- XDBT *key, *val;
- Xint set;
- X{
- X key->size = collect_key ( bufp, 0, val, set );
- X if ( key->size == -1 ) {
- X return (-1);
- X }
- X key->data = hashp->tmp_key;
- X return(0);
- X}
- X
- X/*
- X Count how big the total key size is by
- X recursing through the pages. Then collect
- X the data, allocate a buffer and copy the key as
- X you recurse up.
- X*/
- Xstatic int
- Xcollect_key ( bufp, len, val, set )
- XBUFHEAD *bufp;
- Xint len;
- XDBT *val;
- Xint set;
- X{
- X char *p = bufp->page;
- X u_short *bp = (u_short *)p;
- X u_short save_addr;
- X int mylen, totlen;
- X BUFHEAD *xbp;
- X
- X mylen = hashp->BSIZE - bp[1];
- X
- X save_addr = bufp->addr;
- X totlen = len + mylen;
- X if ( bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA ) {/* End of Key */
- X if ( hashp->tmp_key ) free (hashp->tmp_key);
- X hashp->tmp_key = (char *)malloc ( totlen );
- X if ( !hashp->tmp_key ) {
- X return(-1);
- X }
- X big_return ( bufp, 1, val, set );
- X } else {
- X xbp = get_buf (bp[bp[0]-1], bufp, 0);
- X if ( !xbp || ((totlen = collect_key (xbp, totlen, val, set)) < 1 ) ) {
- X return(-1);
- X }
- X }
- X if ( bufp->addr != save_addr ) {
- X errno = EINVAL; /* MIS -- OUT OF BUFFERS */
- X return (-1);
- X }
- X bcopy ( (bufp->page) + bp[1], &hashp->tmp_key[len], mylen );
- X return ( totlen );
- X}
- X
- X
- X/*
- X return 0 => OK
- X -1 => error
- X*/
- Xextern int
- Xbig_split ( op, np, big_keyp, addr, obucket, ret )
- XBUFHEAD *op; /* Pointer to where to put keys that go in old bucket */
- XBUFHEAD *np; /* Pointer to new bucket page */
- XBUFHEAD *big_keyp; /* Pointer to first page containing the big key/data */
- Xu_short addr; /* Address of big_keyp */
- Xint obucket; /* Old Bucket */
- XSPLIT_RETURN *ret;
- X{
- X register u_short *prev_pagep;
- X register BUFHEAD *tmpp;
- X register u_short *tp;
- X BUFHEAD *bp = big_keyp;
- X u_short off, free_space;
- X u_short n;
- X
- X DBT key, val;
- X
- X int change;
- X
- X /* Now figure out where the big key/data goes */
- X if (big_keydata ( big_keyp, 1, &key, &val, 0 )) {
- X return(-1);
- X }
- X change = (call_hash ( key.data, key.size ) != obucket );
- X
- X if ( ret->next_addr = find_last_page ( &big_keyp ) ) {
- X if (!(ret->nextp = get_buf ( ret->next_addr, big_keyp, 0 ))) {
- X return(-1);;
- X }
- X } else {
- X ret->nextp = NULL;
- X }
- X
- X /* Now make one of np/op point to the big key/data pair */
- X assert(np->ovfl == NULL);
- X if ( change ) tmpp = np;
- X else tmpp = op;
- X
- X tmpp->flags |= BUF_MOD;
- X#ifdef DEBUG1
- X fprintf ( stderr, "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
- X (tmpp->ovfl?tmpp->ovfl->addr:0),
- X (bp?bp->addr:0) );
- X#endif
- X tmpp->ovfl = bp; /* one of op/np point to big_keyp */
- X tp = (u_short *)tmpp->page;
- X assert ( FREESPACE(tp) >= OVFLSIZE);
- X n = tp[0];
- X off = OFFSET(tp);
- X free_space = FREESPACE(tp);
- X tp[++n] = addr;
- X tp[++n] = OVFLPAGE;
- X tp[0] = n;
- X OFFSET(tp) = off;
- X FREESPACE(tp) = free_space - OVFLSIZE;
- X
- X /*
- X Finally, set the new and old return values.
- X BIG_KEYP contains a pointer to the last page of the big key_data pair.
- X Make sure that big_keyp has no following page (2 elements) or create
- X an empty following page.
- X */
- X
- X ret->newp = np;
- X ret->oldp = op;
- X
- X tp = (u_short *)big_keyp->page;
- X big_keyp->flags |= BUF_MOD;
- X if ( tp[0] > 2 ) {
- X /*
- X There may be either one or two offsets on this page
- X If there is one, then the overflow page is linked on
- X normally and tp[4] is OVFLPAGE. If there are two, tp[4]
- X contains the second offset and needs to get stuffed in
- X after the next overflow page is added
- X */
- X n = tp[4];
- X free_space = FREESPACE(tp);
- X off = OFFSET(tp);
- X tp[0] -= 2;
- X FREESPACE(tp) = free_space + OVFLSIZE;
- X OFFSET(tp) = off;
- X tmpp = add_ovflpage ( big_keyp );
- X if ( !tmpp ) {
- X return(-1);
- X }
- X tp[4] = n;
- X } else {
- X tmpp = big_keyp;
- X }
- X
- X if ( change ) ret->newp = tmpp;
- X else ret->oldp = tmpp;
- X
- X return(0);
- X}
- @@@End of lq-text/src/ozmahash/big.c
- echo x - lq-text/src/ozmahash/buf.c 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/buf.c <<'@@@End of lq-text/src/ozmahash/buf.c'
- X/*-
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Margo Seltzer.
- X *
- X * %sccs.include.redist.c%
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "%W% (Berkeley) %G%";
- X#endif /* LIBC_SCCS and not lint */
- X/******************************************************************************
- X
- XPACKAGE: hash
- X
- XDESCRIPTION:
- X Contains buffer management
- X
- XROUTINES:
- X External
- X buf_init
- X get_buf
- X buf_free
- X reclaim_buf
- X Internal
- X newbuf
- X
- X******************************************************************************/
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <assert.h>
- X#include <errno.h>
- X#include <hash.h>
- X#include <stdio.h>
- X
- X/* Externals */
- Xextern HTAB *hashp;
- X
- X/* My internals */
- Xstatic BUFHEAD *newbuf();
- X
- X/* Unlink B from its place in the lru */
- X#define BUF_REMOVE(B) \
- X{ \
- X B->prev->next = B->next; \
- X B->next->prev = B->prev; \
- X}
- X
- X/* Insert B after P */
- X#define BUF_INSERT(B,P) \
- X{ \
- X B->next = P->next; \
- X B->prev = P; \
- X P->next = B; \
- X B->next->prev = B; \
- X}
- X
- X#define MRU hashp->bufhead.next
- X#define LRU hashp->bufhead.prev
- X
- X#define MRU_INSERT(B) BUF_INSERT(B,(&hashp->bufhead))
- X#define LRU_INSERT(B) BUF_INSERT(B,LRU)
- X
- X/*
- X We are looking for a buffer with address "addr".
- X If prev_bp is NULL, then address is a bucket index.
- X If prev_bp is not NULL, then it points to the page previous
- X to an overflow page that we are trying to find.
- X
- X CAVEAT: The buffer header accessed via prev_bp's ovfl field
- X may no longer be valid. Therefore, you must always verify that
- X its address matches the address you are seeking.
- X*/
- Xextern BUFHEAD *
- Xget_buf ( addr, prev_bp, newpage )
- Xint addr;
- XBUFHEAD *prev_bp;
- Xint newpage; /* If prev_bp is set, indicates that this is
- X a new overflow page */
- X{
- X register int segment_ndx;
- X register BUFHEAD *bp;
- X register unsigned is_disk = 0;
- X SEGMENT segp;
- X
- X if ( prev_bp ) {
- X bp = prev_bp->ovfl;
- X if ( !bp || (bp->addr != addr) ) bp = NULL;
- X if ( !newpage ) is_disk = BUF_DISK;
- X }
- X else {
- X /* Grab buffer out of directory */
- X segment_ndx = addr & ( hashp->SGSIZE - 1 );
- X
- X /*
- X * valid segment ensured by call_hash()
- X */
- X segp = hashp->dir[addr >> hashp->SSHIFT];
- X#ifdef DEBUG
- X assert(segp != NULL);
- X#endif
- X bp = PTROF(segp[segment_ndx]);
- X is_disk = ISDISK(segp[segment_ndx]);
- X }
- X
- X if ( !bp ) {
- X bp = newbuf ( addr, prev_bp );
- X if ( !bp || get_page ( bp->page, addr, !prev_bp, (int)is_disk, 0 )) {
- X return(NULL);
- X }
- X if ( !prev_bp ) {
- X segp[segment_ndx] = (BUFHEAD *)((unsigned)bp | is_disk);
- X }
- X } else {
- X BUF_REMOVE ( bp );
- X MRU_INSERT ( bp );
- X }
- X return(bp);
- X}
- X
- X/*
- X We need a buffer for this page. Either allocate one, or
- X evict a resident one (if we have as many buffers as we're
- X allowed) and put this one in.
- X
- X If newbuf finds an error (returning NULL), it also sets errno
- X*/
- Xstatic BUFHEAD *
- Xnewbuf ( addr, prev_bp )
- Xint addr;
- XBUFHEAD *prev_bp;
- X{
- X register BUFHEAD *bp; /* The buffer we're going to use */
- X register BUFHEAD *xbp; /* Temp pointer */
- X register BUFHEAD *next_xbp;
- X int segment_ndx;
- X u_short *shortp;
- X u_short oaddr;
- X SEGMENT segp;
- X
- X if ( hashp->nbufs ) {
- X /* Allocate a new one */
- X bp = (BUFHEAD *)malloc ( sizeof (struct _bufhead) );
- X if ( !bp || !(bp->page = (char *)malloc ( hashp->BSIZE )) ) {
- X return (NULL);
- X }
- X hashp->nbufs--;
- X } else {
- X /* Kick someone out */
- X bp = LRU;
- X BUF_REMOVE( bp );
- X /*
- X Set oaddr before put_page so that you get it
- X before bytes are swapped
- X */
- X shortp = (u_short *)bp->page;
- X oaddr = shortp[shortp[0]-1];
- X if ( (bp->flags & BUF_MOD) &&
- X put_page(bp->page, bp->addr, (int)IS_BUCKET(bp->flags), 0) ) {
- X return(NULL);
- X }
- X /*
- X Update the pointer to this page (i.e. invalidate it).
- X
- X If this is a new file (i.e. we created it at open time),
- X make sure that we mark pages which have been written to
- X disk so we retrieve them from disk later, rather than
- X allocating new pages.
- X */
- X
- X if ( IS_BUCKET(bp->flags)) {
- X segment_ndx = bp->addr & ( hashp->SGSIZE - 1 );
- X
- X segp = hashp->dir[bp->addr >> hashp->SSHIFT];
- X
- X assert(segp != NULL);
- X
- X if ( hashp->new_file &&
- X ((bp->flags & BUF_MOD) || ISDISK(segp[segment_ndx])) ) {
- X segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
- X } else segp[segment_ndx] = NULL;
- X }
- X
- X /*
- X Since overflow pages can only be access by means of
- X their bucket, free overflow pages associated with this
- X bucket.
- X */
- X for ( xbp = bp; xbp->ovfl; ) {
- X
- X next_xbp = xbp->ovfl;
- X xbp->ovfl = 0;
- X xbp = next_xbp;
- X
- X /* Check that ovfl pointer is up date */
- X if ( IS_BUCKET(xbp->flags) || (oaddr != xbp->addr) ) break;
- X
- X shortp = (u_short *)xbp->page;
- X oaddr = shortp[shortp[0]-1]; /* set before put_page */
- X if ( (xbp->flags & BUF_MOD) &&
- X put_page ( xbp->page, xbp->addr, 0, 0 ) ) {
- X return(NULL);
- X }
- X xbp->addr = 0;
- X xbp->flags = 0;
- X BUF_REMOVE ( xbp );
- X LRU_INSERT ( xbp );
- X }
- X }
- X
- X /* Now assign this buffer */
- X bp->addr = addr;
- X#ifdef DEBUG1
- X fprintf ( stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", bp->addr,
- X (bp->ovfl?bp->ovfl->addr:0), 0);
- X#endif
- X bp->ovfl = NULL;
- X if ( prev_bp ) {
- X /*
- X If prev_bp is set, this is an overflow page, hook it in to the
- X buffer overflow links
- X */
- X#ifdef DEBUG1
- X fprintf ( stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", prev_bp->addr,
- X (prev_bp->ovfl?bp->ovfl->addr:0),
- X (bp?bp->addr: 0));
- X#endif
- X prev_bp->ovfl = bp;
- X bp->flags = 0;
- X } else bp->flags = BUF_BUCKET;
- X MRU_INSERT ( bp );
- X return ( bp );
- X}
- X
- Xextern void
- Xbuf_init ( nbytes )
- Xint nbytes;
- X{
- X int npages;
- X BUFHEAD *bfp = &(hashp->bufhead);
- X
- X npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
- X npages = MAX ( npages, MIN_BUFFERS );
- X
- X hashp->nbufs = npages;
- X bfp->next = bfp;
- X bfp->prev = bfp;
- X /*
- X This space is calloc'd so these are already null
- X
- X bfp->ovfl = NULL;
- X bfp->flags = 0;
- X bfp->page = NULL;
- X bfp->addr = 0;
- X */
- X}
- X
- Xextern int
- Xbuf_free ( do_free, to_disk )
- Xint do_free;
- Xint to_disk;
- X{
- X BUFHEAD *bp;
- X
- X /* Need to make sure that buffer manager has been initialized */
- X if ( !LRU ) {
- X return(0);
- X }
- X
- X for ( bp = LRU; bp != &hashp->bufhead; ) {
- X /* Check that the buffer is valid */
- X if ( bp->addr || IS_BUCKET(bp->flags) ) {
- X if ( to_disk && (bp->flags & BUF_MOD) &&
- X put_page (bp->page, bp->addr, IS_BUCKET(bp->flags)), 0 ) {
- X return (-1);
- X }
- X }
- X
- X /* Check if we are freeing stuff */
- X if ( do_free ) {
- X if ( bp->page ) free ( bp->page );
- X BUF_REMOVE(bp);
- X (void)free ( bp );
- X bp = LRU;
- X } else bp = bp->prev;
- X }
- X
- X return(0);
- X}
- X
- Xextern void
- Xreclaim_buf ( bp )
- XBUFHEAD *bp;
- X{
- X bp->ovfl = 0;
- X bp->addr = 0;
- X bp->flags = 0;
- X BUF_REMOVE ( bp );
- X LRU_INSERT ( bp );
- X}
- @@@End of lq-text/src/ozmahash/buf.c
- echo x - lq-text/src/ozmahash/byte_order.c 1>&2
- sed 's/^X//' >lq-text/src/ozmahash/byte_order.c <<'@@@End of lq-text/src/ozmahash/byte_order.c'
- X/*-
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Margo Seltzer.
- X *
- X * %sccs.include.redist.c%
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "%W% (Berkeley) %G%";
- X#endif /* LIBC_SCCS and not lint */
- X
- X#include <stdio.h>
- Xmain ( argc, argv )
- Xint argc;
- Xchar **argv;
- X{
- X int num = 0x41424344;
- X if ( ((((char *)&num)[0]) == 0x41) && ((((char *)&num)[1]) == 0x42) &&
- X ((((char *)&num)[2]) == 0x43) && ((((char *)&num)[3]) == 0x44) ) {
- X printf ( "BIG ENDIAN\n" );
- X } else if ( ((((char *)&num)[3]) == 0x41) &&
- X ((((char *)&num)[2]) == 0x42) &&
- X ((((char *)&num)[1]) == 0x43) &&
- X ((((char *)&num)[0]) == 0x44) ) {
- X printf ( "LITTLE ENDIAN\n" );
- X } else {
- X printf ( "Odd Endian -- are you running on a PDP-11?\n");
- X }
- X
- X}
- @@@End of lq-text/src/ozmahash/byte_order.c
- echo x - lq-text/src/menu/error.c 1>&2
- sed 's/^X//' >lq-text/src/menu/error.c <<'@@@End of lq-text/src/menu/error.c'
- X/* Error.c -- print an error message and exit.
- X * If we're in curses mode, do an endwin() first.
- X *
- X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/error.c,v 1.1 90/08/29 21:49:49 lee Rel1-10 $
- X *
- X * $Log: error.c,v $
- X * Revision 1.1 90/08/29 21:49:49 lee
- X * Initial revision
- X *
- X * Revision 2.1 89/08/07 13:49:36 lee
- X * First fully working (V.3.2 only) release;
- X * this is the baseline for future development.
- X *
- X * Revision 1.2 89/08/04 17:59:14 lee
- X * Fully working with Basic Functionality.
- X * Scrolling menubar, scrolling menus, moveable Info windows.
- X *
- X *
- X */
- X
- X#include <stdio.h>
- X#ifdef ultrix
- X# include <cursesX.h>
- X#else
- X# include <curses.h>
- X#endif
- X#include <malloc.h>
- X#include "internal.h"
- X#include "error.h"
- X
- Xint InCurses = 0;
- Xextern char *cmdname, *progname;
- X
- X/*PRINTFLIKE1*/
- X/*VARARGS1*/
- Xvoid
- Xerror(Type, fmt, a1, a2, a3, a4)
- X int Type;
- X char *fmt;
- X{
- X extern char *strchr();
- X char *p;
- X extern char *malloc();
- X
- X if (InCurses) {
- X if (!(Type & (ERR_INTERNAL | ERR_MEMORY))) {
- X if ((p = malloc(500)) == (char *) 0) {
- X Type |= ERR_MEMORY;
- X } else {
- X (void) sprintf(p, fmt, a1, a2, a3, a4);
- X (void) ShowInfo(p, (WINDOW *) 0, COLS / 2 - 20, LINES / 2 - 4);
- X if (Type & ERR_FATAL) {
- X endwin();
- X exit(1);
- X } else {
- X return;
- X }
- X }
- X }
- X if (Type & ERR_FATAL) {
- X endwin();
- X exit(1);
- X }
- X }
- X if (InCurses) {
- X if (Type & ERR_FATAL) {
- X endwin();
- X InCurses = 0;
- X }
- X }
- X if (InCurses && !(Type & ERR_INTERNAL)) {
- X wmove(stdscr, 5, 0);
- X clrtoeol();
- X refresh();
- X }
- X if (cmdname) {
- X (void) fprintf(stderr, "%s: ", cmdname);
- X }
- X if (progname) {
- X (void) fprintf(stderr, "%s: ", progname);
- X }
- X (void) fprintf(stderr, fmt, a1, a2, a3, a4);
- X if (strchr(fmt, '\n') == (char *) 0) {
- X (void) fputc('\n', stderr);
- X }
- X if (InCurses) fputc('\r', stderr);
- X if (Type & ERR_FATAL) exit(-1);
- X}
- @@@End of lq-text/src/menu/error.c
- echo x - lq-text/src/menu/error.h 1>&2
- sed 's/^X//' >lq-text/src/menu/error.h <<'@@@End of lq-text/src/menu/error.h'
- X/* Codes that can be passed to error()
- X *
- X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/error.h,v 1.1 90/08/29 21:49:53 lee Rel1-10 $
- X *
- X * $Log: error.h,v $
- X * Revision 1.1 90/08/29 21:49:53 lee
- X * Initial revision
- X *
- X * Revision 2.1 89/08/07 13:48:38 lee
- X * First fully working (V.3.2 only) release;
- X * this is the baseline for future development.
- X *
- X * Revision 1.1 89/07/28 19:11:06 lee
- X * Initial revision
- X *
- X *
- X */
- X
- Xextern void error();
- X
- X#define ERR_INTERNAL 01
- X#define ERR_MEMORY 02
- X#define ERR_FATAL 04
- @@@End of lq-text/src/menu/error.h
- echo x - lq-text/src/menu/internal.h 1>&2
- sed 's/^X//' >lq-text/src/menu/internal.h <<'@@@End of lq-text/src/menu/internal.h'
- X/* internal.h -- header file for internal use.
- X *
- X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/internal.h,v 1.1 90/08/29 21:50:36 lee Rel1-10 $
- X *
- X * $Log: internal.h,v $
- X * Revision 1.1 90/08/29 21:50:36 lee
- X * Initial revision
- X *
- X * Revision 2.1 89/08/07 13:49:27 lee
- X * First fully working (V.3.2 only) release;
- X * this is the baseline for future development.
- X *
- X * Revision 1.1 89/07/27 11:39:40 lee
- X * Initial revision
- X *
- X *
- X */
- X
- X/* Thanks to Henry Spencer (utzoo!henry) for this: */
- X#define STREQ(boy,girl) ((*(boy)== *(girl))&&!strcmp((boy),(girl)))
- X
- X
- X/* SAVEMENULINE is set if you want to the menus to hang down from
- X * the bar when selected. (this is default)
- X * Otherwise, define MENUTEXTOVERBAR and recompile...
- X * the top line of the menu goes on screen row MENUTOP.
- X * If MENUTOP is >= 2, the top line of the menu is boxed. Otherwise,
- X * the first item in the menu goes on the menu line, overwriting it.
- X * Only use this if you have (ROWS - 1) items on each menu...
- X */
- X
- X#ifndef MENUTEXTOERBAR
- X# define SAVEMENULINE
- X#endif
- X#define SAVEMENULINE
- X#ifdef SAVEMENULINE
- X /* MENUTOP is the line on which pull-down menus start. */
- X# ifndef MENUTOP
- X# define MENUTOP 2
- X# endif /*!MENUTOP*/
- X# if MENUTOP>1
- X# define MENUBOXONTOPLINE
- X# endif
- X#else
- X# define MENUTOP 1
- X# undef MENUBOXONTOPLINE
- X#endif
- X
- X#define new(type) ((type *) malloc(sizeof(type)))
- @@@End of lq-text/src/menu/internal.h
- echo x - lq-text/src/menu/menu.h 1>&2
- sed 's/^X//' >lq-text/src/menu/menu.h <<'@@@End of lq-text/src/menu/menu.h'
- X#ifdef ultrix
- X# include "ultrixhack.h"
- X#endif
- X/* menu.h -- user programs should include this after curses.h
- X *
- X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/menu.h,v 1.1 90/08/29 21:50:50 lee Rel1-10 $
- X *
- X * $Log: menu.h,v $
- X * Revision 1.1 90/08/29 21:50:50 lee
- X * Initial revision
- X *
- X * Revision 2.1 89/08/07 13:49:31 lee
- X * First fully working (V.3.2 only) release;
- X * this is the baseline for future development.
- X *
- X * Revision 1.2 89/08/04 17:59:07 lee
- X * Fully working with Basic Functionality.
- X * Scrolling menubar, scrolling menus, moveable Info windows.
- X *
- X * Revision 1.1 89/07/27 11:39:20 lee
- X * Initial revision
- X *
- X *
- X */
- X
- X/* for errors... -- set this whenever initscr() is in effect */
- Xextern int InCurses;
- X
- X/* A menu bar from a data structures (how quaint!) viewpoint:
- X *
- X * File Edit *Implement* Duration
- X * -------------+---------------+------------------------------------
- X * | Tongs |
- X * | *Whip******** |
- X * | Branding Iron |
- X * | Thumbscrew |
- X * | Dead Fish |
- X * +---------------+
- X *
- X * MenuBar ---> +-----------------------------------------------------
- X * |HowManyMenus = 4
- X * |SelectedMenu = 2
- X * |MenuBarId [internal] = 34 (say)
- X * |ScrollOffset = 0 // horizontal scrolling of bar
- X * |Menus--->an array of 4 menu structures:
- X * |
- X *
- X * MenuBar->Menus[2] looks like this:
- X * +-----------------------------------------------------
- X * |Name = "Implement"
- X * |HowManyItems = 5
- X * |NeedToBox = 1
- X * |IsSelected = 1 // it's highlighted in the MenuBar
- X * |TopLineOnScreen = 0 // for vertical scrolling
- X * |PositionInBar = 13 // characters from the left
- X * |Width = 14 // length of widest item
- X * |SelectedLine = 1 // they're numbered from 0
- X * |MenuId [private] = 4097 (say)
- X * |Description = "Choose a torture implement..."
- X * |Items--->an array of 5 items:
- X * |
- X *
- X * MenuBar->Menus[2]->Items[1] looks like this:
- X * +-----------------------------------------------------
- X * |Function-->points to a function to be called when
- X * |Name = "Whip"
- X * |NameLength = 4 // strlen(Name), for speed
- X * |Description = "Cat O' Nine Tails"
- X * |LongText = "Ouch" // passed to Function().
- X */
- X
- Xtypedef struct {
- X int (*Function)();
- X /* Function is called when the menu is selected. If it is
- X * zero, you just get a beep(); this is intended for testing.
- X * The function is passed two arguments: a pointer to the menu
- X * which contained this item, and the item number. In the
- X * "Whip" example above, it would be a pointer to the Implement
- X * menu, and the number "1".
- X * The LongText argumenht is intended for use by this function,
- X * although what it does with it is undefined. For example,
- X * it could contain a shell command, or it could be a pointer
- X * into a table of statements to be interpreted, or....
- X */
- X char *Name;
- X /* Name is the string displayed in the menu itself.
- X */
- X unsigned short NameLength;
- X /* NameLength must either be 0 or strlen(Name). In the former case,
- X * it will automatically be updated. It is not clear that this is
- X * a big saving, so it may well go way soon.
- X */
- X char *Description;
- X /* pop-up box for help/explanation; when the item is highlighted,
- X * the user can press `?' or `x' and get this short explanation in
- X * a pop-up box.
- X */
- X char *LongText;
- X /* for use only by Function -- see the comment there.
- X */
- X} t_MenuItem;
- X
- X/* For MenuStyle, see below */
- X#ifndef MENUSTYLE_DEFAULT
- X# define MENUSTYLE_DEFAULT 0
- X#endif
- X
- X/* Each menu structure holds (a pointer to) a number of Items...*/
- Xtypedef struct {
- X int HowManyItems;
- X /* This can of course be less than the real number, if you want to
- X * shorten a menu for some reason. If there are more items than
- X * will fit on the screen, the menu can scroll vertically, so there
- X * is no limit imposed on this by the menu routines. On the other
- X * hand, it would be so irritating to scroll through 1000 items that
- X * the list should preferably be under 20.
- X */
- X t_MenuItem *Items;
- X /* This is a pointer to a block of menus.
- X * A linked list might be better.
- X */
- X unsigned int MenuStyle;
- X /* currently always zero, as there is only one style.
- X * you can use MENUSTYLE_DEFAULT for this.
- X * A future style might have no box, just a line on the left.
- X */
- X unsigned int IsSelected : 1;
- X /* This is in case you are using interrupts to change menus. You
- X * wouldn't want to delete or hide a selected menu!
- X * The software updates this, but otherwise ignores it.
- X */
- X int TopLineOnScreen;
- X /* This is for vertical scrolling; if it's 13 (say), then the
- X * first 13 lines of the menu are not displayed -- If it was "1" in
- X * the example, "Whip" would be where "Tongs" are, and "Tongs"
- X * would not be displayed.
- X */
- X int PositionInBar;
- X /* Horizontal position of the left edge of the box. This is set
- X * for each menu by ShowMenuBar() at each call.
- X */
- X int Width;
- X /* The same as the length of the longest item.
- X * If you change the items, set this to zero to force ShowMenuBar()
- X * or ShowMenu() to recalculate it from the Item->[*].Width entries,
- X * or using strlen() if necessary.
- X */
- X char *Name;
- X int NameLength;
- X /* This is the text displayed on the menu bar.
- X * NameLength is computed by ShowMenuBar(); the user should set it
- X * to zero to indicate that this is necessary, when the menu is
- X * created and whenever the name changes.
- X */
- X char *Description;
- X /* This should be a short (one line) description of the purpose
- X * of this menu.
- X */
- X int SelectedLine;
- X /* This is the currently highlighted line. If you set it yourself,
- X * ShowMenu() will make this the highlighted item when it first
- X * displays the menu. Subsequently, of course, the user will move
- X * it up or down at will...
- X * The default is zero, the first item.
- X */
- X /* private */ int MenuId;
- X /* Set this to zero. */
- X} t_Menu;
- X
- X#define MENUMAXINBAR 30
- X
- X/* A Menu Bar... */
- Xtypedef struct {
- X int HowManyMenus;
- X /* The number of menus in Menus[]. Only the first MENUMAXINBAR will
- X * be used, however. Also, not all will be displayed on the screen...
- X * depending on how many fit.
- X */
- X int SelectedMenu;
- X /* This is the Menu whose name is highlighted.
- X * Default is zero; set it to something else if you want...
- X */
- X t_Menu *Menus[MENUMAXINBAR];
- X /* Pointers to the menu structures */
- X int ScrollOffset;
- X /* This is for horizontal scrolling.
- X * The default is zero, meaning that the first menu is as near to the
- X * left of the screen as it will go (there's a 2-char gap to make
- X * room for the left edge of the box).
- X */
- X /* private */ int MenuBarId;
- X /* Set this to zero. */
- X} t_MenuBar;
- X
- X/* Some functions that you can arrange to have called by menu selection.
- X * The functions in this table must all take two arguments, a t_Menu *
- X * and an integer, which represents the (menu, item) combination that
- X * was selected.
- X * They should return either the integer or -1.
- X * If they return -3 or -4, it's the same as if the user pressed the
- X * left or right arrow keys instead of selecting.
- X * If they return -5, it's as if they typed 'q' at the prompt.
- X */
- X
- X/*PRINTFLIKE1*/
- Xextern void error();
- X
- X/* A TextBox has the following structure:
- X *
- X * +------------------------------------------
- X * | Name (optional, only displayed if != 0)
- X * | Flags
- X * | BoldName
- X * | BoldText
- X * | CanEdit
- X * | IfChanged (set if the text has been edited)
- X * | Window (0 if not allocated)
- X * | tlx, tly -- where it is
- X * | Height, Width -- how big it is (including the surrounding box)
- X * | char *Text -- the text itself
- X * | HowManyLines
- X * | short *LineLengths --> pointer to array of line lengths
- X * | HScrollPos, VScrollPos
- X */
- Xtypedef struct s_TextBox {
- X char *Name;
- X unsigned long flags;
- X WINDOW *Window;
- X short tlx, tly;
- X short Height, Width;
- X int HScrollPos, VScrollPos;
- X char *String;
- X int HowManyLines;
- X short *LineLengths;
- X int StringWidth;
- X} t_StringBox;
- X
- @@@End of lq-text/src/menu/menu.h
- echo end of part 11
- --
- Liam R. E. Quin, lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
-