summaryrefslogtreecommitdiffstats
path: root/contrib/less/ch.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-05-09 01:35:27 +0000
committerdelphij <delphij@FreeBSD.org>2009-05-09 01:35:27 +0000
commit810e5a84b4607c4d0fc76e9a418ae9fd2b0eeeb2 (patch)
tree5e0628caeff31611fab89dbdf72053148a59a873 /contrib/less/ch.c
parent8583a840068803e7fd9e0fc2452605bca6e822d8 (diff)
downloadFreeBSD-src-810e5a84b4607c4d0fc76e9a418ae9fd2b0eeeb2.zip
FreeBSD-src-810e5a84b4607c4d0fc76e9a418ae9fd2b0eeeb2.tar.gz
Update to less v429.
Diffstat (limited to 'contrib/less/ch.c')
-rw-r--r--contrib/less/ch.c248
1 files changed, 144 insertions, 104 deletions
diff --git a/contrib/less/ch.c b/contrib/less/ch.c
index eb607d5..8ad028b 100644
--- a/contrib/less/ch.c
+++ b/contrib/less/ch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1984-2007 Mark Nudelman
+ * Copyright (C) 1984-2008 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -37,20 +37,19 @@ public int ignore_eoi;
* in order from most- to least-recently used.
* The circular list is anchored by the file state "thisfile".
*/
+struct bufnode {
+ struct bufnode *next, *prev;
+ struct bufnode *hnext, *hprev;
+};
+
#define LBUFSIZE 8192
struct buf {
- struct buf *next, *prev;
- struct buf *hnext, *hprev;
+ struct bufnode node;
BLOCKNUM block;
unsigned int datasize;
unsigned char data[LBUFSIZE];
};
-
-struct buflist {
- /* -- Following members must match struct buf */
- struct buf *buf_next, *buf_prev;
- struct buf *buf_hnext, *buf_hprev;
-};
+#define bufnode_buf(bn) ((struct buf *) bn)
/*
* The file state is maintained in a filestate structure.
@@ -58,8 +57,8 @@ struct buflist {
*/
#define BUFHASH_SIZE 64
struct filestate {
- struct buf *buf_next, *buf_prev;
- struct buflist hashtbl[BUFHASH_SIZE];
+ struct bufnode buflist;
+ struct bufnode hashtbl[BUFHASH_SIZE];
int file;
int flags;
POSITION fpos;
@@ -69,8 +68,8 @@ struct filestate {
POSITION fsize;
};
-#define ch_bufhead thisfile->buf_next
-#define ch_buftail thisfile->buf_prev
+#define ch_bufhead thisfile->buflist.next
+#define ch_buftail thisfile->buflist.prev
#define ch_nbufs thisfile->nbufs
#define ch_block thisfile->block
#define ch_offset thisfile->offset
@@ -79,23 +78,48 @@ struct filestate {
#define ch_flags thisfile->flags
#define ch_file thisfile->file
-#define END_OF_CHAIN ((struct buf *)&thisfile->buf_next)
-#define END_OF_HCHAIN(h) ((struct buf *)&thisfile->hashtbl[h])
+#define END_OF_CHAIN (&thisfile->buflist)
+#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h])
#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1))
-#define FOR_BUFS_IN_CHAIN(h,bp) \
- for (bp = thisfile->hashtbl[h].buf_hnext; \
- bp != END_OF_HCHAIN(h); bp = bp->hnext)
+/*
+ * Macros to manipulate the list of buffers in thisfile->buflist.
+ */
+#define FOR_BUFS(bn) \
+ for (bn = ch_bufhead; bn != END_OF_CHAIN; bn = bn->next)
+
+#define BUF_RM(bn) \
+ (bn)->next->prev = (bn)->prev; \
+ (bn)->prev->next = (bn)->next;
+
+#define BUF_INS_HEAD(bn) \
+ (bn)->next = ch_bufhead; \
+ (bn)->prev = END_OF_CHAIN; \
+ ch_bufhead->prev = (bn); \
+ ch_bufhead = (bn);
+
+#define BUF_INS_TAIL(bn) \
+ (bn)->next = END_OF_CHAIN; \
+ (bn)->prev = ch_buftail; \
+ ch_buftail->next = (bn); \
+ ch_buftail = (bn);
+
+/*
+ * Macros to manipulate the list of buffers in thisfile->hashtbl[n].
+ */
+#define FOR_BUFS_IN_CHAIN(h,bn) \
+ for (bn = thisfile->hashtbl[h].hnext; \
+ bn != END_OF_HCHAIN(h); bn = bn->hnext)
-#define HASH_RM(bp) \
- (bp)->hnext->hprev = (bp)->hprev; \
- (bp)->hprev->hnext = (bp)->hnext;
+#define BUF_HASH_RM(bn) \
+ (bn)->hnext->hprev = (bn)->hprev; \
+ (bn)->hprev->hnext = (bn)->hnext;
-#define HASH_INS(bp,h) \
- (bp)->hnext = thisfile->hashtbl[h].buf_hnext; \
- (bp)->hprev = END_OF_HCHAIN(h); \
- thisfile->hashtbl[h].buf_hnext->hprev = (bp); \
- thisfile->hashtbl[h].buf_hnext = (bp);
+#define BUF_HASH_INS(bn,h) \
+ (bn)->hnext = thisfile->hashtbl[h].hnext; \
+ (bn)->hprev = END_OF_HCHAIN(h); \
+ thisfile->hashtbl[h].hnext->hprev = (bn); \
+ thisfile->hashtbl[h].hnext = (bn);
static struct filestate *thisfile;
static int ch_ungotchar = -1;
@@ -119,17 +143,12 @@ static int ch_addbuf();
/*
* Get the character pointed to by the read pointer.
- * ch_get() is a macro which is more efficient to call
- * than fch_get (the function), in the usual case
- * that the block desired is at the head of the chain.
*/
-#define ch_get() ((ch_block == ch_bufhead->block && \
- ch_offset < ch_bufhead->datasize) ? \
- ch_bufhead->data[ch_offset] : fch_get())
int
-fch_get()
+ch_get()
{
register struct buf *bp;
+ register struct bufnode *bn;
register int n;
register int slept;
register int h;
@@ -139,52 +158,69 @@ fch_get()
if (thisfile == NULL)
return (EOI);
+ /*
+ * Quick check for the common case where
+ * the desired char is in the head buffer.
+ */
+ if (ch_bufhead != END_OF_CHAIN)
+ {
+ bp = bufnode_buf(ch_bufhead);
+ if (ch_block == bp->block && ch_offset < bp->datasize)
+ return bp->data[ch_offset];
+ }
+
slept = FALSE;
/*
* Look for a buffer holding the desired block.
*/
h = BUFHASH(ch_block);
- FOR_BUFS_IN_CHAIN(h, bp)
+ FOR_BUFS_IN_CHAIN(h, bn)
{
+ bp = bufnode_buf(bn);
if (bp->block == ch_block)
{
if (ch_offset >= bp->datasize)
/*
* Need more data in this buffer.
*/
- goto read_more;
+ break;
goto found;
}
}
- /*
- * Block is not in a buffer.
- * Take the least recently used buffer
- * and read the desired block into it.
- * If the LRU buffer has data in it,
- * then maybe allocate a new buffer.
- */
- if (ch_buftail == END_OF_CHAIN || ch_buftail->block != -1)
+ if (bn == END_OF_HCHAIN(h))
{
/*
- * There is no empty buffer to use.
- * Allocate a new buffer if:
- * 1. We can't seek on this file and -b is not in effect; or
- * 2. We haven't allocated the max buffers for this file yet.
+ * Block is not in a buffer.
+ * Take the least recently used buffer
+ * and read the desired block into it.
+ * If the LRU buffer has data in it,
+ * then maybe allocate a new buffer.
*/
- if ((autobuf && !(ch_flags & CH_CANSEEK)) ||
- (maxbufs < 0 || ch_nbufs < maxbufs))
- if (ch_addbuf())
- /*
- * Allocation failed: turn off autobuf.
- */
- autobuf = OPT_OFF;
+ if (ch_buftail == END_OF_CHAIN ||
+ bufnode_buf(ch_buftail)->block != -1)
+ {
+ /*
+ * There is no empty buffer to use.
+ * Allocate a new buffer if:
+ * 1. We can't seek on this file and -b is not in effect; or
+ * 2. We haven't allocated the max buffers for this file yet.
+ */
+ if ((autobuf && !(ch_flags & CH_CANSEEK)) ||
+ (maxbufs < 0 || ch_nbufs < maxbufs))
+ if (ch_addbuf())
+ /*
+ * Allocation failed: turn off autobuf.
+ */
+ autobuf = OPT_OFF;
+ }
+ bn = ch_buftail;
+ bp = bufnode_buf(bn);
+ BUF_HASH_RM(bn); /* Remove from old hash chain. */
+ bp->block = ch_block;
+ bp->datasize = 0;
+ BUF_HASH_INS(bn, h); /* Insert into new hash chain. */
}
- bp = ch_buftail;
- HASH_RM(bp); /* Remove from old hash chain. */
- bp->block = ch_block;
- bp->datasize = 0;
- HASH_INS(bp, h); /* Insert into new hash chain. */
read_more:
pos = (ch_block * LBUFSIZE) + bp->datasize;
@@ -309,24 +345,20 @@ fch_get()
}
found:
- if (ch_bufhead != bp)
+ if (ch_bufhead != bn)
{
/*
* Move the buffer to the head of the buffer chain.
* This orders the buffer chain, most- to least-recently used.
*/
- bp->next->prev = bp->prev;
- bp->prev->next = bp->next;
- bp->next = ch_bufhead;
- bp->prev = END_OF_CHAIN;
- ch_bufhead->prev = bp;
- ch_bufhead = bp;
+ BUF_RM(bn);
+ BUF_INS_HEAD(bn);
/*
* Move to head of hash chain too.
*/
- HASH_RM(bp);
- HASH_INS(bp, h);
+ BUF_HASH_RM(bn);
+ BUF_HASH_INS(bn, h);
}
if (ch_offset >= bp->datasize)
@@ -386,6 +418,7 @@ end_logfile()
sync_logfile()
{
register struct buf *bp;
+ register struct bufnode *bn;
int warned = FALSE;
BLOCKNUM block;
BLOCKNUM nblocks;
@@ -393,24 +426,23 @@ sync_logfile()
nblocks = (ch_fpos + LBUFSIZE - 1) / LBUFSIZE;
for (block = 0; block < nblocks; block++)
{
- for (bp = ch_bufhead; ; bp = bp->next)
+ int wrote = FALSE;
+ FOR_BUFS(bn)
{
- if (bp == END_OF_CHAIN)
- {
- if (!warned)
- {
- error("Warning: log file is incomplete",
- NULL_PARG);
- warned = TRUE;
- }
- break;
- }
+ bp = bufnode_buf(bn);
if (bp->block == block)
{
write(logfile, (char *) bp->data, bp->datasize);
+ wrote = TRUE;
break;
}
}
+ if (!wrote && !warned)
+ {
+ error("Warning: log file is incomplete",
+ NULL_PARG);
+ warned = TRUE;
+ }
}
}
@@ -424,11 +456,13 @@ buffered(block)
BLOCKNUM block;
{
register struct buf *bp;
+ register struct bufnode *bn;
register int h;
h = BUFHASH(block);
- FOR_BUFS_IN_CHAIN(h, bp)
+ FOR_BUFS_IN_CHAIN(h, bn)
{
+ bp = bufnode_buf(bn);
if (bp->block == block)
return (TRUE);
}
@@ -510,7 +544,8 @@ ch_end_seek()
public int
ch_beg_seek()
{
- register struct buf *bp, *firstbp;
+ register struct bufnode *bn;
+ register struct bufnode *firstbn;
/*
* Try a plain ch_seek first.
@@ -522,13 +557,15 @@ ch_beg_seek()
* Can't get to position 0.
* Look thru the buffers for the one closest to position 0.
*/
- firstbp = bp = ch_bufhead;
- if (bp == END_OF_CHAIN)
+ firstbn = ch_bufhead;
+ if (firstbn == END_OF_CHAIN)
return (1);
- while ((bp = bp->next) != END_OF_CHAIN)
- if (bp->block < firstbp->block)
- firstbp = bp;
- ch_block = firstbp->block;
+ FOR_BUFS(bn)
+ {
+ if (bufnode_buf(bn)->block < bufnode_buf(firstbn)->block)
+ firstbn = bn;
+ }
+ ch_block = bufnode_buf(firstbn)->block;
ch_offset = 0;
return (0);
}
@@ -628,7 +665,7 @@ ch_setbufspace(bufspace)
public void
ch_flush()
{
- register struct buf *bp;
+ register struct bufnode *bn;
if (thisfile == NULL)
return;
@@ -646,8 +683,10 @@ ch_flush()
/*
* Initialize all the buffers.
*/
- for (bp = ch_bufhead; bp != END_OF_CHAIN; bp = bp->next)
- bp->block = -1;
+ FOR_BUFS(bn)
+ {
+ bufnode_buf(bn)->block = -1;
+ }
/*
* Figure out the size of the file, if we can.
@@ -694,6 +733,7 @@ ch_flush()
ch_addbuf()
{
register struct buf *bp;
+ register struct bufnode *bn;
/*
* Allocate and initialize a new buffer and link it
@@ -704,11 +744,10 @@ ch_addbuf()
return (1);
ch_nbufs++;
bp->block = -1;
- bp->next = END_OF_CHAIN;
- bp->prev = ch_buftail;
- ch_buftail->next = bp;
- ch_buftail = bp;
- HASH_INS(bp, 0);
+ bn = &bp->node;
+
+ BUF_INS_TAIL(bn);
+ BUF_HASH_INS(bn, 0);
return (0);
}
@@ -722,8 +761,8 @@ init_hashtbl()
for (h = 0; h < BUFHASH_SIZE; h++)
{
- thisfile->hashtbl[h].buf_hnext = END_OF_HCHAIN(h);
- thisfile->hashtbl[h].buf_hprev = END_OF_HCHAIN(h);
+ thisfile->hashtbl[h].hnext = END_OF_HCHAIN(h);
+ thisfile->hashtbl[h].hprev = END_OF_HCHAIN(h);
}
}
@@ -733,14 +772,13 @@ init_hashtbl()
static void
ch_delbufs()
{
- register struct buf *bp;
+ register struct bufnode *bn;
while (ch_bufhead != END_OF_CHAIN)
{
- bp = ch_bufhead;
- bp->next->prev = bp->prev;
- bp->prev->next = bp->next;
- free(bp);
+ bn = ch_bufhead;
+ BUF_RM(bn);
+ free(bufnode_buf(bn));
}
ch_nbufs = 0;
init_hashtbl();
@@ -786,7 +824,7 @@ ch_init(f, flags)
*/
thisfile = (struct filestate *)
calloc(1, sizeof(struct filestate));
- thisfile->buf_next = thisfile->buf_prev = END_OF_CHAIN;
+ thisfile->buflist.next = thisfile->buflist.prev = END_OF_CHAIN;
thisfile->nbufs = 0;
thisfile->flags = 0;
thisfile->fpos = 0;
@@ -867,6 +905,7 @@ ch_getflags()
ch_dump(struct filestate *fs)
{
struct buf *bp;
+ struct bufnode *bn;
unsigned char *s;
if (fs == NULL)
@@ -878,8 +917,9 @@ ch_dump(struct filestate *fs)
fs->file, fs->flags, fs->fpos,
fs->fsize, fs->block, fs->offset);
printf(" %d bufs:\n", fs->nbufs);
- for (bp = fs->buf_next; bp != (struct buf *)fs; bp = bp->next)
+ for (bn = fs->next; bn != &fs->buflist; bn = bn->next)
{
+ bp = bufnode_buf(bn);
printf("%x: blk %x, size %x \"",
bp, bp->block, bp->datasize);
for (s = bp->data; s < bp->data + 30; s++)
OpenPOWER on IntegriCloud