[net.lang.c] Roff in C

bph@ut-ngp.UUCP (hine, butler) (01/01/85)

[]
>The posting of the C version of roff created the following comment:

>> The posted version of this program does not work and was apparently
>> never tested.  As posted, any request at the beginning of a text file
>> causes the whole file to be skipped because of a logic error in the
>> basic input routine, called "suck()." ...

>The statement about an initial request gobbling the whole file is just plain
>false.  I have tested it with a few different requests as the first line of
>the text file, without any problems.  It would have been nice if the person
>had told us what request caused this error.

>Tim Maroney, Carnegie-Mellon University Computation Center

This difference of opinion points up a very interesting problem: in testing
the original "roff.c" I was not using the PCC compiler, but used two others
instead -- DeSmet's C88 and CI-C86 on an IBM PC.  Both behaved exactly the
same way -- *any* request (dot command) caused the input text to be discarded.
However, it does *not* have this effect under PCC, as Tim points out.  I found
out why:

Here's the offending code:
_____________________________________________________________________________
int
suck()
{
	for (;;) {
		c=getc(File);
		if (!iscntrl(c) && c!='\013' && c!='\f' && c!='\r') return c;
	}
}
____________________________________________________________________________

and here's how the manual defines "iscntrl()":

iscntrl             c is a delete character (0177) or ordinary
                    control character (less than 040).

BOTH of the stated compilers failed to interpret "ordinary" in the same way
as the PCC routine of the same name -- they return TRUE if the code is less
than octal 040.  As written, then, with this interpretation, newlines are
never returned, and the text is lost.  PCC, however, excludes newlines,
backspace codes, carriage return codes and a few others, presumably because
they are not "ordinary."  

This says something fairly awful about "portability."

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (01/02/85)

> This difference of opinion points up a very interesting problem: in testing
> the original "roff.c" I was not using the PCC compiler, but used two others
> instead -- DeSmet's C88 and CI-C86 on an IBM PC.  Both behaved exactly the
> same way -- *any* request (dot command) caused the input text to be discarded.
> However, it does *not* have this effect under PCC, as Tim points out.  I found
> out why:
> 
> Here's the offending code:
> _____________________________________________________________________________
> int
> suck()
> {
> 	for (;;) {
> 		c=getc(File);
> 		if (!iscntrl(c) && c!='\013' && c!='\f' && c!='\r') return c;
> 	}
> }
> ____________________________________________________________________________
> 
> and here's how the manual defines "iscntrl()":
> 
> iscntrl             c is a delete character (0177) or ordinary
>                     control character (less than 040).
> 
> BOTH of the stated compilers failed to interpret "ordinary" in the same way
> as the PCC routine of the same name -- they return TRUE if the code is less
> than octal 040.  As written, then, with this interpretation, newlines are
> never returned, and the text is lost.  PCC, however, excludes newlines,
> backspace codes, carriage return codes and a few others, presumably because
> they are not "ordinary."  
> 
> This says something fairly awful about "portability."

This says something fairly awful about available C implementations!

"ordinary" in the description of iscntrl is not an additional qualifier
but an explanatory one.  iscntrl( c ) should return non-zero for c in
{ 0, 1, ..., 036, 037, 0177 } and zero for c in
{ 040, 041, ..., 0175, 0176 }.  It is illegal to supply any other value
of c to the macro/function, although most implementations permit EOF (-1).

The "suck()" routine as written (apart from lack of declaration of the
variable `c') has redundancy in the condition, since c cannot equal any
of the three explicit control characters if it does not pass iscntrl().

"PCC" has nothing to do with the ctype macros; they are defined in
/usr/include/ctype.h (or equivalent on non-UNIX) and usually use a table
loaded from the standard C library.