Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jan 2012 00:47:37 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Kostik Belousov <kostikbel@gmail.com>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Guy Helmer <ghelmer@freebsd.org>
Subject:   Re: svn commit: r229986 - head/lib/libutil
Message-ID:  <20120112235635.Y1663@besplex.bde.org>
In-Reply-To: <20120112001630.GS31224@deviant.kiev.zoral.com.ua>
References:  <201201112233.q0BMXfgD079582@svn.freebsd.org> <20120112001630.GS31224@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 12 Jan 2012, Kostik Belousov wrote:

> On Wed, Jan 11, 2012 at 10:33:41PM +0000, Guy Helmer wrote:
>> Log:
>>   Fix namespace issues with prototype parameter names.
>>   Add missing prototype parameter names.
>>
>>   Requested by bde.
>> ...
>> Modified: head/lib/libutil/libutil.h
>> ==============================================================================
>> --- head/lib/libutil/libutil.h	Wed Jan 11 22:12:45 2012	(r229985)
>> +++ head/lib/libutil/libutil.h	Wed Jan 11 22:33:41 2012	(r229986)
>> @@ -93,7 +93,7 @@ struct termios;
>>  struct winsize;
>>
>>  __BEGIN_DECLS
>> -char	*auth_getval(const char *name);
>> +char	*auth_getval(const char *_name);
> The _[a-z].* names are still in the app namespace.
>
> Only _[A-Z].* and __[a-z].* are reserved for the implementation.

No, _[a-z].* is reserved for the implementation in file scope mainly
for extern declarations).  For example, _exit is reserved for the
implementation, and _name is reserved for the implementation in exactly
the same contexts as _exit is.  This prevents the application #defining
_name as '_this is not a C identifier', which would break the above.
OTOH, _name is not reserved for the implementation in most other scopes,
so applications can do almost anything with it except #define it or
use it for a global or file-scope-static variable or function.

style(9) even gives the exact rule (it says "an underscore" instead
of "a single underscore", but uses only 1 in its example) to inhibit
excessive underscoring in prototypes.

Other details:
- prototypes start a new scope so names in them are not subject to
   the file scope rules
- similarly for struct scope.
- the scopes naturally prevent -Wshadow warnings.  E.g., names inside
   file-scope prototypes in implementation headers can't shadow
   application names, since the application names would have to be
   in file scope so they cannot have a single leading underscore.  I
   haven't thought about all cases for this.

Details from C99 (n869.txt):

%        7.1.3  Reserved identifiers
% 
%          -- All  identifiers  that  begin  with  an  underscore are
%             always reserved for use as identifiers with file  scope
%             in both the ordinary and tag name spaces.
%        ...
%        [#2]  No  other  identifiers  are  reserved.  If the program
%        declares or defines an identifier in a context in  which  it
%        is  reserved  (other than as allowed by 7.1.4), or defines a
%        reserved  identifier  as  a  macro  name,  the  behavior  is
%        undefined.

I think we only need the reservation of _[a-z]* (actually _[a-z0-9]*)
and the anti-definition rule for these to prove that the implementation's
use of _[a-z0-9]* in non-file scope cannot conflict with any application
use of _[a-z0-9]* any scope (can only be non-file scope).

See <stdio.h> for old examples of using the precise rules for avoiding
excessive underscoring, and complications in macros which require 2
underscores:
- struct __sbuf has 2 underscores since it's in file scope
- members in this struct and others have only 1 underscore since they
   are not in file scope
- __sgetc() has 2 underscores, since it is used in getc().  getc() is
   used in function scope where _sgetc is in the application namespace.
   Thus, the implementation cannot use _sgetc here.
- __sgetc() is implemented as an inline function.  The names of parameters
   and local variables in this must have at least 1 underscore so that
   the application cannot #define them, and 1 is enough and only 1 is
   used for the same reasons as for parameter names in prototypes.
- older implementations had an alternative definition of __sgetc() as
   a macro.  Here no underscores are needed (and none are used) for the
   parameter names, since macro parameters have their own namespace and
   so cannot be corrupted by application #define's of their names which
   are now possible.  These use the same single-undescored names for
   struct members.  When I started writing this, I misremembered a
   complication here.  I thought that some struct member names might
   need 2 underscores for such use.  But there is no problem -- (p)->_w
   is protected enough by the single underscore in _w, in the same way
   as for inline functioms.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120112235635.Y1663>