[comp.unix.questions] Some questions about POSIX headers

ast@cs.vu.nl (Andy Tanenbaum) (11/11/89)

I have several questions about POSIX P1003.1.  Consider the following
excerpt from <sys/wait.h>:

#define _LOW(__v)               ( (__v) & 0377)
#define _HIGH(__v)              ( ((__v) >> 8) & 0377)

#define WIFEXITED(__s)		(_LOW(__s) == 0)	      /* normal exit */
#define WEXITSTATUS(__s)	(_HIGH(__s))	 	      /* exit status */
#define WTERMSIG(__s)		(_LOW(__s) & 0177)	      /* sig value */
#define WIFSIGNALED(__s)	(_HIGH(__s) == 0 && __s != 0) /* signaled */

1. Is it legal to have _LOW and _HIGH here (name space pollution rules)?
2. Are the parameters __s and __v required to begin with __ (again, name
   space pollution rules)?
3. WIFSIGNALED evaluates __s twice.  Is this legal?  In an ANSI C header
   it is specifically forbidden.  What about POSIX?
4. Is the extra set of parenthesis around __v in _HIGH() really required?
5. What is the best newsgroup for asking this sort of question?

Thanks.

Andy Tanenbaum (ast@cs.vu.nl)

karish@forel.stanford.edu (Chuck Karish) (11/14/89)

In article <4508@ast.cs.vu.nl> ast@cs.vu.nl (Andy Tanenbaum) wrote:
>I have several questions about POSIX P1003.1.  Consider the following
>excerpt from <sys/wait.h>:
>
>#define _LOW(__v)               ( (__v) & 0377)
>#define _HIGH(__v)              ( ((__v) >> 8) & 0377)
>
>#define WIFEXITED(__s)		(_LOW(__s) == 0)	      /* normal exit */
>#define WEXITSTATUS(__s)	(_HIGH(__s))	 	      /* exit status */
>#define WTERMSIG(__s)		(_LOW(__s) & 0177)	      /* sig value */
>#define WIFSIGNALED(__s)	(_HIGH(__s) == 0 && __s != 0) /* signaled */

>1. Is it legal to have _LOW and _HIGH here (name space pollution rules)?
>2. Are the parameters __s and __v required to begin with __ (again, name
>   space pollution rules)?

    [ CAVEAT:  I've read what I believe to be the relevant parts of
    the 1003.1 standard and the May, 1988 X3J11 draft.  The people
    who wrote those documents understand more of the motivations
    behind them.  I go by what I read. ]

    When C Standard Language-Dependent Support is provided, POSIX
    1003.1 defers to the ANSI C name-space-pollution rules.  When
    a feature test macro is #defined, it makes visible the set of
    symbols specified by that macro, in addition to the symbols
    specified by the C standard.  The usual case for portable
    POSIX applications is that the _POSIX_SOURCE feature test
    macro will be #defined, so the C standard symbols and the
    POSIX 1003.1 symbols will be visible.

    Under ANSI C, _LOW, _HIGH, __s, and __v are all reserved to the
    library implementor if they're external identifiers, because they
    all start with underscores.  In any standard header, they'll
    become externals when the header is #included with external scope.

    The question now becomes, is the header part of the library
    implementation or not?  If any compiler other than the native one
    will use these headers, the answer had best be `not'.

    These identifiers are OK with file scope or smaller inside a C
    library implementation, but not as external identifiers.

>3. WIFSIGNALED evaluates __s twice.  Is this legal?  In an ANSI C header
>   it is specifically forbidden.  What about POSIX?

    Explicitly forbidden.  Section 2.2.4.

>4. Is the extra set of parenthesis around __v in _HIGH() really required?

    No.  `>>' has higher precedence than `&'.  Even so, when in doubt,
    parenthesize.  It makes the code easier for humans to read, and
    doesn't make it significantly more difficult for compilers
    to read.

>5. What is the best newsgroup for asking this sort of question?

    comp.std.unix; comp.std.c; comp.lang.c (point 4).

>Thanks.
>
>Andy Tanenbaum (ast@cs.vu.nl)

    You're welcome.

    If my interpretation is incorrect, someone please speak up.
    I want to understand this stuff.

	Chuck Karish		karish@mindcraft.com
	(415) 493-9000		karish@forel.stanford.edu

gwyn@smoke.BRL.MIL (Doug Gwyn) (11/14/89)

In article <4508@ast.cs.vu.nl> ast@cs.vu.nl (Andy Tanenbaum) writes:
>1. Is it legal to have _LOW and _HIGH here (name space pollution rules)?

Yes; they're in the name space reserved for the implementation.

>2. Are the parameters __s and __v required to begin with __ (again, name
>   space pollution rules)?

It doesn't matter one way or the other.  Parameter names in the macro
definition are not visible elsewhere.

>3. WIFSIGNALED evaluates __s twice.  Is this legal?  In an ANSI C header
>   it is specifically forbidden.  What about POSIX?

Unfortunately I don't have my copy of IEEE Std 1003.1 on hand.
Whether or not 1003.1 specified this I don't recall, but I doubt it.
On the other hand it probably SHOULD have been specified, so the
implementation would be better if it obeyed that constraint.

>4. Is the extra set of parenthesis around __v in _HIGH() really required?

Yes, to ensure proper operator binding when the actual argument is
an expression.

>5. What is the best newsgroup for asking this sort of question?

Probably comp.std.c, although for more POSIX-specific questions
comp.std.unix might be better.

karish@forel.stanford.edu (Chuck Karish) (11/15/89)

As I expected when I answered these questions yesterday, there were
some subtleties I hadn't appreciated.  Doug Gwyn pointed some of them
out in another answer, but he didn't get them all, either.

In article <6622@portia.Stanford.EDU> karish@forel.stanford.edu
(Chuck Karish) wrote:
>In article <4508@ast.cs.vu.nl> ast@cs.vu.nl (Andy Tanenbaum) wrote:
>>I have several questions about POSIX P1003.1.  Consider the following
>>excerpt from <sys/wait.h>:
>>#define _LOW(__v)               ( (__v) & 0377)
>>#define _HIGH(__v)              ( ((__v) >> 8) & 0377)
>>#define WIFSIGNALED(__s)	(_HIGH(__s) == 0 && __s != 0) /* signaled */
>
>>1. Is it legal to have _LOW and _HIGH here (name space pollution rules)?

>    These identifiers are OK with file scope or smaller inside a C
>    library implementation, but not as external identifiers.


[ Doug said that _LOW and _HIGH are OK in a header. ]

According to Section 2.8.2.1 of the 1003.1 document, "If there are no
feature test macros present in a program, only the set of symbols
defined by the C standard shall be present".  This means that the
symbols may be present, but they must be concealed by a feature test
macro:

#ifdef	_C_LIBRARY
#define _LOW(__v)               ( (__v) & 0377)
#define _HIGH(__v)              ( ((__v) >> 8) & 0377)
#endif

Any program that wants to use them must #define that feature
test macro before the header is #included.  There may be a number
of feature test macros in effect.  Each one makes visible a
specific set of identifiers.  Identifiers specified by 1003.1
are to be visible only if the _POSIX_SOURCE macro is #defined
before the header is #included.  Note that this macro should
have been called _POSIX1_SOURCE; other macros will be used for
other POSIX standards.

A header that conforms to POSIX 1003.1 as well as to the SVID and
X/OPEN standards will be a bit complicated.  A SVID-conforming program
that doesn't use POSIX extensions will expect UNIX identifiers to be
visible in the headers without use of a feature test macro.

>>3. WIFSIGNALED evaluates __s twice.  Is this legal?  In an ANSI C header
>>   it is specifically forbidden.  What about POSIX?
>
>    Explicitly forbidden.  Section 2.2.4.

Section 2.2.4 says "Any invocation of a library function that is
implemented as a macro shall expand to code that evaluates each of its
arguments only once ...".  However, WIFSIGNALED is defined in the
Standard as a macro, not as a library function.  It's legal to
evaluate these arguments twice; maybe not wise but, strictly
speaking, legal.

>>4. Is the extra set of parenthesis around __v in _HIGH() really required?
>    No.  `>>' has higher precedence than `&'.

Doug says `yes', and he's right.  If __v is an expression that includes
an operator with lower precedence than `&', there will be trouble
if the parentheses are omitted.

	Chuck Karish		karish@mindcraft.com
	(415) 323-9000		karish@forel.stanford.edu

goudreau@dg-rtp.dg.com (Bob Goudreau) (11/15/89)

In article <6622@portia.Stanford.EDU> karish@forel.stanford.edu (Chuck Karish) writes:
>
>    Under ANSI C, _LOW, _HIGH, __s, and __v are all reserved to the
>    library implementor if they're external identifiers, because they
>    all start with underscores.  In any standard header, they'll
>    become externals when the header is #included with external scope.
>
>    The question now becomes, is the header part of the library
>    implementation or not?  If any compiler other than the native one
>    will use these headers, the answer had best be `not'.
>
>    These identifiers are OK with file scope or smaller inside a C
>    library implementation, but not as external identifiers.

Here's what the Dec. 7, 1988 ANSI draft says about the matter:

	4.1.2.1  Reserved Identifiers

	Each header declares or defines all identifiers listed in its
	associated section, and optionally declares or defines
	identifiers listed in its associated future library directions
	section and identifiers which are always reserved either for
	any use or for use as file scope identifiers.

	+  All identifiers that begin with an underscore and either an
	   upper-case letter or another underscore are always reserved
	   for any use.

	+  All identifiers that begin with an underscore are always
	   reserved for use as identifiers with file scope in both the
	   ordinary identifier and tag name spaces.

	....


Since _LOW, _HIGH, __s and __v all fall into the first category ("always
reserved for any use"), the implementation is free to do what it wants
with them.  But note that if _s had been used instead of __s, only the
second category would have applied.

------------------------------
Bob Goudreau				+1 919 248 6231
Data General Corporation		...!mcnc!rti!xyzzy!goudreau
62 Alexander Drive			goudreau@dg-rtp.dg.com
Research Triangle Park, NC  27709, USA

rml@hpfcdc.HP.COM (Bob Lenk) (11/15/89)

>#define _LOW(__v)               ( (__v) & 0377)
>#define _HIGH(__v)              ( ((__v) >> 8) & 0377)
>
>#define WIFEXITED(__s)		(_LOW(__s) == 0)	      /* normal exit */
>#define WEXITSTATUS(__s)	(_HIGH(__s))	 	      /* exit status */
>#define WTERMSIG(__s)		(_LOW(__s) & 0177)	      /* sig value */
>#define WIFSIGNALED(__s)	(_HIGH(__s) == 0 && __s != 0) /* signaled */

> 1. Is it legal to have _LOW and _HIGH here (name space pollution rules)?

Yes.  They are in the namespace reserved for the implementation.

> 2. Are the parameters __s and __v required to begin with __ (again, name
>    space pollution rules)?

No.  The names of macro parameters do no impact the application's
namespace in any way.  They could be called printf and fork without
any problem.

> 3. WIFSIGNALED evaluates __s twice.  Is this legal?  In an ANSI C header
>    it is specifically forbidden.  What about POSIX?

I see no explicit restriction in POSIX (since these are described as
macros rather than functions).  At least in theory it's a bad idea.  In
practice, because WIFSIGNALED() is only meaningful if the argument is a
value returned via wait() or waitpid(), I see no reasonable way for its
argument to be an expression that would be harmful to evaluate twice.  I
could concoct some legal POSIX usage where the status is written to a
file and then an application does

	WIFSIGNALED(getc(stream))

> 4. Is the extra set of parenthesis around __v in _HIGH() really required?

Similar answer to (3).  In this case concoct something like

	WEXITSTATUS(status + 0)

> 5. What is the best newsgroup for asking this sort of question?

This one seems reasonable to me.  Comp.std.unix would also be appropriate.

Of course these are my personal opinions only.  A binding interpretation
can only be issued by the IEEE (as described in the published standard).

		Bob Lenk
		rml@hpfcla.hp.com
		hplabs!hpfcla!rml

rml@hpfcdc.HP.COM (Bob Lenk) (11/18/89)

> According to Section 2.8.2.1 of the 1003.1 document, "If there are no
> feature test macros present in a program, only the set of symbols
> defined by the C standard shall be present".  This means that the
> symbols may be present, but they must be concealed by a feature test
> macro:
> 
> #ifdef	_C_LIBRARY
> #define _LOW(__v)               ( (__v) & 0377)
> #define _HIGH(__v)              ( ((__v) >> 8) & 0377)
> #endif

I would lean toward interpreting "the set of symbols defined by the
C Standard" as including the possibility of any symbols reserved for
the implementation by the C Standard.  I see no benefit, and many
problems, with any other interpretation.  Consider that such symbols
might legally be reserved words.

In this specific case, I expect the macros in question would (or could)
fall within #ifdef _POSIX_SOURCE, which makes the issue moot.

Of course, this is just my personal opinion.  Only the IEEE can issue
binding interpretations

		Bob Lenk
		rml@hpfcla.hp.com
		hplabs!hpfcla!rml

karish@forel.stanford.edu (Chuck Karish) (11/19/89)

In article <5740045@hpfcdc.HP.COM> rml@hpfcdc.HP.COM (Bob Lenk) wrote:
[Chuck Karish wrote:]
>> According to Section 2.8.2.1 of the 1003.1 document, "If there are no
>> feature test macros present in a program, only the set of symbols
>> defined by the C standard shall be present".  This means that the
>> symbols may be present, but they must be concealed by a feature test
>> macro...

>I would lean toward interpreting "the set of symbols defined by the
>C Standard" as including the possibility of any symbols reserved for
>the implementation by the C Standard.  I see no benefit, and many
>problems, with any other interpretation.  Consider that such symbols
>might legally be reserved words.

I agree with Bob, and with Doug Gwyn, that 1003.1 should allow symbols
reserved for the implementation by the C standard to be visible in the
standard headers.  I disagree that it is reasonable to interpret
`defined' to mean `reserved'.  The symbols required by the C standard
to be defined in the standard headers are neatly listed in Appendix 3
of that document.

Now that explicit provision has been made for use of symbols from the
reserved namespace when _POSIX_SOURCE is defined, but not otherwise
(1003.1a, Drafts 3 and 4, Section 2.8.2) it is more clear than ever
that the standard restricts visibility of such symbols.

The standard is broken.  For the case where only the C standard should
apply to the contents of headers, the 1003.1 standard is more
restrictive than the C standard.  We should make sure that it gets
fixed, rather than spend our time with corrective misinterpretations.