Missing stdio features.

der Mouse mouse at mcgill-vision.UUCP
Thu Sep 4 15:32:38 AEST 1986


In article <6224 at sri-spam.ARPA>, argv at sri-spam.ARPA (AAAARRRRGGGGv) writes:
[>> is AAAARRRRGGGGv quoting me]
>> Here are the things I have wanted badly enough to add to stdio:
>> FILE *fopenfxn(int (*fxn)(), char *mode)
>>	Function-stream I/O.  Returns a FILE*, open for read or write
>> 	(not both, "r+" is treated as "r").  When a character is
>> 	written to (resp. read from) the stream, the function is
>> 	called.
> This shouldn't be that hard to do:
> first, take the fildes of the open stream, set it to be asynch IO,
> then loop.  When data is there to be read, you'll get a SIGIO.  For
> some strange reason, I seem to remember that this is can only be done
> on pseudo-tty's or other types of devices (I use it frequently for
> windows on the SUN); so I don't know if this will work well on normal
> files or sockets.
(By the way, the "strange reason" is that the code isn't in the kernel
for it!)
[excerpted example follows:]
> int fd = open ("/dev/tty", 0);
> signal (SIGIO, io_handler);
> ioctl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | FASYNC));
> io_handler()
> {
>     puts("Hey, there's data to be read on the fildes!");
> }

You apparently misunderstood (ok, let's be nice, I didn't make myself
clear).  What fopenfxn does is not what the above does (or even what it
appears to be trying to do).  There is no file descriptor associated
with a function stream!  For example, if we do
	f = fopenfxn(foo_fxn,"w");
then
	putc(c,f);
and
	foo_fxn(c,f);
are equivalent.  The advantage is that functions like printf() can be
used on the resulting stream, and call the function once for each
character generated.  Reading works analogously:
	f = fopenfxn(foo_fxn,"r");
	c = getc(f);
is equivalent to
	c = foo_fxn(f);
but makes scanf() and friends work as well.

>> FILE *fopenstr(char *str, int len, char *mode)
>> 	An extension to sprintf() and sscanf().  This returns a stream
>> 	which performs I/O to a string (this makes sprintf() and
>> 	sscanf() unnecessay, though they are still convenient).
>
> I request you more fully describe this functionality. I don't see how
> adding the routines of an IO library is going to speed up what
> sprintf and sscanf already do.  Perhaps to do something like this
> would be "interesting", but that's about it.  Again, please
> elaborate.

Sure.

	f = fopenstr(buf,"w");
	fprintf(f,"Current square is: ");
	print_square(f,current_square);
	fprintf(f,"and no other!");
	fclose(f);

Or

	f = fopenstr(buf,"w");
	fprintf(f,"List is:");
	for (element=list;element;element=element->link)
	 { fprintf(f," %d",element->value);
	 }
	fprintf(f,".");
	fclose(f);

Using this instead of sprintf or sscanf should produce no speed
difference (well, actually, it should be slightly slower because of the
extra function calls involved....).

>> unfdopen(FILE *f)
>> 	Undoes fdopen(), that is, closes the FILE* without close()ing
>> 	the underlying file descriptor.
> This would be nice.

Yeah.  To get it with vanilla stdio requires playing games with dup,
and will cause lots more pain if (as for stdin/out/err) you want the
original descriptor number.  Even then, you gotta have a descriptor
free.

>> Unfdopen is trivial; fopenfxn and fopenstr are implemented by making
>> the stream appear unbuffered to putc and getc and then changing _flsbuf
>> and _filbuf to add the functionality.
>
> Looking at the source to puts (fputs) and so forth, I've found that
> it is much faster to never unbuffer anything and to simply macro that
> which you'd like to have "unbuffered":
> #define unbuffered_puts(s,f)   fputs(s,f), fflush(f)

The point of telling stdio that the stream is unbuffered is that then
other stdio functions such as printf and scanf will call _flsbuf (resp.
_filbuf) for every character.

> The reason for this is that if the data is unbuffered, fputs merely
> sets the buffer to a buffer within the routine, sets a few flags,
> goes thru a while loop, using the macro in stdio to putc to the
> stream, then fflushes again, finally resettting all the flags it
> started with.  Finallly (not that this has anything to do with it),
> it returns the last character put to the stream (undocumented).

You are running 4.3, right?  It was fun making these work when we
shifted to 4.3....4.2 puts (and similar functions) didn't do this
"let's pretend it's buffered for a little while...." trick.

> In any event, what's preventing you from free()ing the structure and
> leaving the fd open?

Huh?  What does this have to do with any of the above?



More information about the Comp.lang.c mailing list