The Unix Heritage Society mailing list
 help / color / Atom feed
* Re: [TUHS] #defines and enums
@ 2019-11-14  1:35 Larry McVoy
  0 siblings, 0 replies; 3+ messages in thread
From: Larry McVoy @ 2019-11-14  1:35 UTC (permalink / raw)
  To: tuhs

FYI.

----- Forwarded message from Linus Torvalds <torvalds@linux-foundation.org> -----

Date: Wed, 13 Nov 2019 12:37:50 -0800
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Larry McVoy <lm@mcvoy.com>
Subject: Re: enum style?

On Wed, Nov 13, 2019 at 10:28 AM Larry McVoy <lm@mcvoy.com> wrote:
>
> and asked what was the point of the #defines.  I couldn't answer, the only
> thing I can think of is so you can say
>
>         int     flags = MS_RDONLY;
>
> Which is cool, but why bother with the enum?

For the kernel we actually have this special "type-safe enum" checker
thing, which warns about assigning one enum type to another.

It's not really C, but it's close. It's the same tool we use for some
other kernel-specific type checking (user pointers vs kernel pointers
etc): 'sparse'.

  http://man7.org/linux/man-pages/man1/sparse.1.html

and in particular the "-Wenum-mismatch" flag to enable that warning
when you assign an enum to another enum.

It's quite useful for verifying that you pass the right kind of enum
to functions etc - which is a really easy mistake to make in C, since
they all just devolve into 'int' when they are used.

However, we don't use it for the MS_xyz flag: those are just plain
#define's in the kernel. But maybe somebody at some point wanted to do
something similar for the ones you point at?

The only other reason I can think of is that somebody really wanted to
use an enum for namespace reasons, and then noticed that other people
had used a #define and used "#ifdef XYZ" to check whether it was
available, and then instead of changing the enums to #defines, they
just added the self-defines.

In the kernel we do that "use #define for discoberability" quite a lot
particularly with architecture-specific helper functions. So you migth
have

   static inline some_arch_fn(..) ...
   #define some_arch_fn some_arch_fn

in an architecture file, and then in generic code we have

   #ifndef some_arch_fn
   static inline some_arch_fn(.,,) /* generic implemenbtation goes here */
   #endif

as a way to avoid extra configuration variables for the "do I have a
special version X?"

There's no way to ask "is the C symbol X available in this scope", so
using the pre-processor for that is as close as you can get.

               Linus

----- End forwarded message -----

-- 
---
Larry McVoy            	     lm at mcvoy.com             http://www.mcvoy.com/lm 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [TUHS] #defines and enums
  2019-11-13 19:15     ` [TUHS] #defines and enums ron
@ 2019-11-13 21:11       ` Warner Losh
  0 siblings, 0 replies; 3+ messages in thread
From: Warner Losh @ 2019-11-13 21:11 UTC (permalink / raw)
  To: Ronald Natalie; +Cc: The Eunuchs Hysterical Society

[-- Attachment #1: Type: text/plain, Size: 1963 bytes --]

On Wed, Nov 13, 2019, 12:15 PM <ron@ronnatalie.com> wrote:

>
> >
> > BTW, I'm doing my first messing around with the Linux kernel these days;
> > if anyone knows the guts of the generic filesystem code I could use a bit
> > of help.  Here's something that I came across on the way in
> <sys/mount.h>:
> >
> > enum
> > {
> >   MS_RDONLY = 1,              /* Mount read-only.  */
> > #define MS_RDONLY     MS_RDONLY
> >   MS_NOSUID = 2,              /* Ignore suid and sgid bits.  */
> > #define MS_NOSUID     MS_NOSUID
> >   MS_NODEV = 4,                       /* Disallow access to device
> special files.  */
> > #define MS_NODEV      MS_NODEV
> > ...
> > };
> >
> > Can anyone explain the value of this programming style?  Is this just an
> > example of the result of how programming is taught today?
> >
> >
>
> This really is more a C question than a UNIX one.    The problem is that
> the preprocessor macros are really kind of a kludge.   Making things
> either enums (or in later C/C++ const int definitions) is a lot cleaner.
>  The #define is just probably backwards a compatibility kludge (for people
> using things like MS_RDONLY or whatever in other macros).
>

It lets the users of these interfaces conditionally use them as ifdef. A
pure enum interface doesn't let you do that. This makes it harder to write
portable code that is driven directly by what is defined.

While it seems purer to use enum, it is problematic. C++ doesn't let you
use it for bit fields due to special rules around enums that aren't there
to get in the way in C.

Conditional code is important, as are providing enough compat scaffolding
when sharing code between many systems, or when different compilers are
used. Macro processing accomplishes this rather well, though not without
other issues. In an ideal world, you could put other constructs into the
language to accomplish these goals... But none that have been good enough
to gain any traction at all....

Warner

>

[-- Attachment #2: Type: text/html, Size: 2805 bytes --]

<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 13, 2019, 12:15 PM  &lt;<a href="mailto:ron@ronnatalie.com">ron@ronnatalie.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
&gt;<br>
&gt; BTW, I&#39;m doing my first messing around with the Linux kernel these days;<br>
&gt; if anyone knows the guts of the generic filesystem code I could use a bit<br>
&gt; of help.  Here&#39;s something that I came across on the way in &lt;sys/mount.h&gt;:<br>
&gt;<br>
&gt; enum<br>
&gt; {<br>
&gt;   MS_RDONLY = 1,              /* Mount read-only.  */<br>
&gt; #define MS_RDONLY     MS_RDONLY<br>
&gt;   MS_NOSUID = 2,              /* Ignore suid and sgid bits.  */<br>
&gt; #define MS_NOSUID     MS_NOSUID<br>
&gt;   MS_NODEV = 4,                       /* Disallow access to device special files.  */<br>
&gt; #define MS_NODEV      MS_NODEV<br>
&gt; ...<br>
&gt; };<br>
&gt;<br>
&gt; Can anyone explain the value of this programming style?  Is this just an<br>
&gt; example of the result of how programming is taught today?<br>
&gt;<br>
&gt;<br>
<br>
This really is more a C question than a UNIX one.    The problem is that<br>
the preprocessor macros are really kind of a kludge.   Making things<br>
either enums (or in later C/C++ const int definitions) is a lot cleaner.  <br>
 The #define is just probably backwards a compatibility kludge (for people<br>
using things like MS_RDONLY or whatever in other macros).<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">It lets the users of these interfaces conditionally use them as ifdef. A pure enum interface doesn&#39;t let you do that. This makes it harder to write portable code that is driven directly by what is defined.</div><div dir="auto"><br></div><div dir="auto">While it seems purer to use enum, it is problematic. C++ doesn&#39;t let you use it for bit fields due to special rules around enums that aren&#39;t there to get in the way in C.</div><div dir="auto"><br></div><div dir="auto">Conditional code is important, as are providing enough compat scaffolding when sharing code between many systems, or when different compilers are used. Macro processing accomplishes this rather well, though not without other issues. In an ideal world, you could put other constructs into the language to accomplish these goals... But none that have been good enough to gain any traction at all....</div><div dir="auto"><br></div><div dir="auto">Warner</div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote></div></div></div>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [TUHS] #defines and enums
  2019-11-13 18:02   ` [TUHS] Happy birthday Morris worm [ really programming education ] Jon Steinhart
@ 2019-11-13 19:15     ` ron
  2019-11-13 21:11       ` Warner Losh
  0 siblings, 1 reply; 3+ messages in thread
From: ron @ 2019-11-13 19:15 UTC (permalink / raw)
  To: Jon Steinhart; +Cc: tuhs


>
> BTW, I'm doing my first messing around with the Linux kernel these days;
> if anyone knows the guts of the generic filesystem code I could use a bit
> of help.  Here's something that I came across on the way in <sys/mount.h>:
>
> enum
> {
>   MS_RDONLY = 1,		/* Mount read-only.  */
> #define MS_RDONLY	MS_RDONLY
>   MS_NOSUID = 2,		/* Ignore suid and sgid bits.  */
> #define MS_NOSUID	MS_NOSUID
>   MS_NODEV = 4,			/* Disallow access to device special files.  */
> #define MS_NODEV	MS_NODEV
> ...
> };
>
> Can anyone explain the value of this programming style?  Is this just an
> example of the result of how programming is taught today?
>
>

This really is more a C question than a UNIX one.    The problem is that
the preprocessor macros are really kind of a kludge.   Making things
either enums (or in later C/C++ const int definitions) is a lot cleaner.  
 The #define is just probably backwards a compatibility kludge (for people
using things like MS_RDONLY or whatever in other macros).



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, back to index

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-14  1:35 [TUHS] #defines and enums Larry McVoy
  -- strict thread matches above, loose matches on Subject: below --
2019-11-12 20:56 [TUHS] Happy birthday Morris worm Norman Wilson
2019-11-13  7:35 ` arnold
2019-11-13 18:02   ` [TUHS] Happy birthday Morris worm [ really programming education ] Jon Steinhart
2019-11-13 19:15     ` [TUHS] #defines and enums ron
2019-11-13 21:11       ` Warner Losh

The Unix Heritage Society mailing list

Archives are clonable: git clone --mirror http://inbox.vuxu.org/tuhs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.tuhs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git