lq-text Full Text Retrieval Database Part 11/13
Liam R. E. Quin
lee at sq.sq.com
Mon Mar 4 12:10:55 AEST 1991
: 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 at sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
More information about the Alt.sources
mailing list