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