needle -filter

José R. Valverde jrvalverde at cnb.uam.es
Thu Jun 12 09:46:05 UTC 2003


> ... of course, I was carefully avoiding mention of GCG format which 
> ruins any plans to use ungetc :-)
> 
> ... and you can't seek back to the position in a pipe
> 
> Peter

OK, time to abandon lurker mode.

	First, this is old stuff. K&R show how to handle this situations in
their classic "The C Programming Language". The same approach may be used 
at any level (i.e. more than one character): simply use a bigger read buffer
(or a dynamic one).

	The code in K&R:

- -------------------------------------------------------------------------

#define BUFSIZE 100

char buf[BUFSIZE];    /* buffer for ungetch */
int bufp = 0;         /* next free position in buf */

int getch(void)  /* get a (possibly pushed-back) character */
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)   /* push character back on input */
{
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

- --------------------------------------------------------------------------

A dynamic one -- i once used something similar on an arcane db-processing 
program to deal with UW-type entries: you couldn't tell them until you 
found the '..' tag, at the end of possibly arbitrarily long comments, since 
one must read the whole entry sooner or later anyway into memory, it's not
that much of a waste to do it like this:


- ---------------------------------------------------------------------------
#include <stdlib.h>

static char *buf;     	    /* buffer for ungetch */
static size_t bufsize = 128;   /* current buffer size */	
size_t bufp = 0;               /* next free position in buf */

ungetch_init()
{
    if ((buf = (char *) malloc(bufsize)) == NULL)
	perror("ungetch_init()");
}

ungetch_exit()
{
    free(buf);
}

int getch(void)  /* get a (possibly pushed-back) character */
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)   /* push character back on input */
{
    if (bufp >= bufsize) {
        /* realloc buf: duplicate its size 
         * might use a linear increase as well, say "+=128" */
	bufsize *= 2;
	if ((buf = (char *) realloc(buf, bufsize)) == NULL)
	    perror("ungetch_init()");
    }
    else
        buf[bufp++] = c;
}

- -----------------------------------------------------------------------

Trivial.

	Second: seeking back. How do 'more' and 'less' manage to seek 
back-forward stdin? How does ghostview=

	The simplest approach: read into a temporary file and, if needed,
seek from it.

	The fastest approach: read everything into memory and move on
memory (this is easier if one may use mmap(), but this is not so easy
with stdin).

	Use a big enough lookeahead buffer and instead of reading char by
char, read entry by entry.

	Use a double buffer:
	one buffer is used for the current entry, the other for the next
one, a switch defines which is the current one. This is another classic,
I can't remember the refference offhand though.

					j




More information about the EMBOSS mailing list