diff mbox series

[v2] manual/stdio: Clarify putc and putwc

Message ID 20240729123225.63285-1-arjun@redhat.com
State New
Headers show
Series [v2] manual/stdio: Clarify putc and putwc | expand

Commit Message

Arjun Shankar July 29, 2024, 12:30 p.m. UTC
The manual entry for `putc' described what "most systems" do instead of
describing the glibc implementation and its guarantees.  This commit
fixes that by warning that putc may be implemented as a macro that
double-evaluates `stream', and removing the performance claim.

Even though the current `putc' implementation does not double-evaluate
`stream', offering this obscure guarantee as an extension to what
POSIX allows does not seem very useful.

The entry for `putwc' is also edited to bring it in line with `putc'.
---
v1: https://sourceware.org/pipermail/libc-alpha/2024-July/158676.html
Changes since v1: Dropped the performance claim.
---
 manual/stdio.texi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Florian Weimer July 29, 2024, 12:49 p.m. UTC | #1
* Arjun Shankar:

> The manual entry for `putc' described what "most systems" do instead of
> describing the glibc implementation and its guarantees.  This commit
> fixes that by warning that putc may be implemented as a macro that
> double-evaluates `stream', and removing the performance claim.
>
> Even though the current `putc' implementation does not double-evaluate
> `stream', offering this obscure guarantee as an extension to what
> POSIX allows does not seem very useful.
>
> The entry for `putwc' is also edited to bring it in line with `putc'.
> ---
> v1: https://sourceware.org/pipermail/libc-alpha/2024-July/158676.html
> Changes since v1: Dropped the performance claim.
> ---
>  manual/stdio.texi | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/manual/stdio.texi b/manual/stdio.texi
> index f5e289d58a..f9529a098d 100644
> --- a/manual/stdio.texi
> +++ b/manual/stdio.texi
> @@ -903,21 +903,21 @@ This function is a GNU extension.
>  @deftypefun int putc (int @var{c}, FILE *@var{stream})
>  @standards{ISO, stdio.h}
>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
> -This is just like @code{fputc}, except that most systems implement it as
> +This is just like @code{fputc}, except that it may be implemented as
>  a macro, making it faster.  One consequence is that it may evaluate the
>  @var{stream} argument more than once, which is an exception to the
> -general rule for macros.  @code{putc} is usually the best function to
> -use for writing a single character.
> +general rule for macros.  Therefore, @var{stream} should never be an
> +expression with side-effects.
>  @end deftypefun
>  
>  @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
>  @standards{ISO, wchar.h}
>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
> -This is just like @code{fputwc}, except that it can be implement as
> +This is just like @code{fputwc}, except that it may be implemented as
>  a macro, making it faster.  One consequence is that it may evaluate the
>  @var{stream} argument more than once, which is an exception to the
> -general rule for macros.  @code{putwc} is usually the best function to
> -use for writing a single wide character.
> +general rule for macros.  Therefore, @var{stream} should never be an
> +expression with side-effects.
>  @end deftypefun
>  
>  @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})

Looks okay to me.

Reviewed-by: Florian Weimer <fweimer@redhat.com>

Thanks,
Florian
Vincent Lefevre July 29, 2024, 1:43 p.m. UTC | #2
On 2024-07-29 14:30:59 +0200, Arjun Shankar wrote:
> diff --git a/manual/stdio.texi b/manual/stdio.texi
> index f5e289d58a..f9529a098d 100644
> --- a/manual/stdio.texi
> +++ b/manual/stdio.texi
> @@ -903,21 +903,21 @@ This function is a GNU extension.
>  @deftypefun int putc (int @var{c}, FILE *@var{stream})
>  @standards{ISO, stdio.h}
>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
> -This is just like @code{fputc}, except that most systems implement it as
> +This is just like @code{fputc}, except that it may be implemented as
>  a macro, making it faster.  One consequence is that it may evaluate the
>  @var{stream} argument more than once, which is an exception to the
> -general rule for macros.  @code{putc} is usually the best function to
> -use for writing a single character.
> +general rule for macros.  Therefore, @var{stream} should never be an
> +expression with side-effects.

I think that the word "consequence" is misleading. This is not just a
consequence (any function may be implemented as a macro, BTW). This is
also because the C standard explicitly allows "stream" to be evaluated
more than once (this is an exception to the general rule). On the
opposite, it is guaranteed that the argument "c" will be evaluated
exactly once.

>  @end deftypefun
>  
>  @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
>  @standards{ISO, wchar.h}
>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
> -This is just like @code{fputwc}, except that it can be implement as
> +This is just like @code{fputwc}, except that it may be implemented as
>  a macro, making it faster.  One consequence is that it may evaluate the
>  @var{stream} argument more than once, which is an exception to the
> -general rule for macros.  @code{putwc} is usually the best function to
> -use for writing a single wide character.
> +general rule for macros.  Therefore, @var{stream} should never be an
> +expression with side-effects.

Ditto.
Andreas Schwab July 29, 2024, 1:51 p.m. UTC | #3
On Jul 29 2024, Vincent Lefevre wrote:

> On 2024-07-29 14:30:59 +0200, Arjun Shankar wrote:
>> diff --git a/manual/stdio.texi b/manual/stdio.texi
>> index f5e289d58a..f9529a098d 100644
>> --- a/manual/stdio.texi
>> +++ b/manual/stdio.texi
>> @@ -903,21 +903,21 @@ This function is a GNU extension.
>>  @deftypefun int putc (int @var{c}, FILE *@var{stream})
>>  @standards{ISO, stdio.h}
>>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
>> -This is just like @code{fputc}, except that most systems implement it as
>> +This is just like @code{fputc}, except that it may be implemented as
>>  a macro, making it faster.  One consequence is that it may evaluate the
>>  @var{stream} argument more than once, which is an exception to the
>> -general rule for macros.  @code{putc} is usually the best function to
>> -use for writing a single character.
>> +general rule for macros.  Therefore, @var{stream} should never be an
>> +expression with side-effects.
>
> I think that the word "consequence" is misleading. This is not just a
> consequence (any function may be implemented as a macro, BTW). This is
> also because the C standard explicitly allows "stream" to be evaluated
> more than once (this is an exception to the general rule).

The same is true for the getc and getwc functions.
Arjun Shankar July 29, 2024, 2:49 p.m. UTC | #4
> >> -This is just like @code{fputc}, except that most systems implement it as
> >> +This is just like @code{fputc}, except that it may be implemented as
> >>  a macro, making it faster.  One consequence is that it may evaluate the
> >>  @var{stream} argument more than once, which is an exception to the
> >> -general rule for macros.  @code{putc} is usually the best function to
> >> -use for writing a single character.
> >> +general rule for macros.  Therefore, @var{stream} should never be an
> >> +expression with side-effects.
> >
> > I think that the word "consequence" is misleading. This is not just a
> > consequence (any function may be implemented as a macro, BTW). This is
> > also because the C standard explicitly allows "stream" to be evaluated
> > more than once (this is an exception to the general rule).

Thanks Vincent. Looks like I should have waited a bit before pushing this.

My plan now is to change:

> This is just like @code{fputc}, except that it may be implemented as
> a macro, making it faster.  One consequence is that it may evaluate the
> @var{stream} argument more than once, which is an exception to the
> general rule for macros.

To:

"This is just like @code{fputc}, except that it may be implemented as
a macro and may evaluate the @var{stream} argument more than once,
which is an exception to the general rule for macros."

> The same is true for the getc and getwc functions.

Thanks Andreas. I'll look at them as well.

Cheers!
Florian Weimer July 29, 2024, 3:18 p.m. UTC | #5
* Arjun Shankar:

>> >> -This is just like @code{fputc}, except that most systems implement it as
>> >> +This is just like @code{fputc}, except that it may be implemented as
>> >>  a macro, making it faster.  One consequence is that it may evaluate the
>> >>  @var{stream} argument more than once, which is an exception to the
>> >> -general rule for macros.  @code{putc} is usually the best function to
>> >> -use for writing a single character.
>> >> +general rule for macros.  Therefore, @var{stream} should never be an
>> >> +expression with side-effects.
>> >
>> > I think that the word "consequence" is misleading. This is not just a
>> > consequence (any function may be implemented as a macro, BTW). This is
>> > also because the C standard explicitly allows "stream" to be evaluated
>> > more than once (this is an exception to the general rule).
>
> Thanks Vincent. Looks like I should have waited a bit before pushing this.
>
> My plan now is to change:
>
>> This is just like @code{fputc}, except that it may be implemented as
>> a macro, making it faster.  One consequence is that it may evaluate the
>> @var{stream} argument more than once, which is an exception to the
>> general rule for macros.
>
> To:
>
> "This is just like @code{fputc}, except that it may be implemented as
> a macro and may evaluate the @var{stream} argument more than once,
> which is an exception to the general rule for macros."

It's still confusing.  The general rule for macros is that they still
need to behave like function calls and evaluate each argument only once.

What about this?

| This is just like @code{fputc}, except that it may be implemented as a
| macro which evaluates the @var{stream} argument more than once.

Thanks,
Florian
diff mbox series

Patch

diff --git a/manual/stdio.texi b/manual/stdio.texi
index f5e289d58a..f9529a098d 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -903,21 +903,21 @@  This function is a GNU extension.
 @deftypefun int putc (int @var{c}, FILE *@var{stream})
 @standards{ISO, stdio.h}
 @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputc}, except that most systems implement it as
+This is just like @code{fputc}, except that it may be implemented as
 a macro, making it faster.  One consequence is that it may evaluate the
 @var{stream} argument more than once, which is an exception to the
-general rule for macros.  @code{putc} is usually the best function to
-use for writing a single character.
+general rule for macros.  Therefore, @var{stream} should never be an
+expression with side-effects.
 @end deftypefun
 
 @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
 @standards{ISO, wchar.h}
 @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputwc}, except that it can be implement as
+This is just like @code{fputwc}, except that it may be implemented as
 a macro, making it faster.  One consequence is that it may evaluate the
 @var{stream} argument more than once, which is an exception to the
-general rule for macros.  @code{putwc} is usually the best function to
-use for writing a single wide character.
+general rule for macros.  Therefore, @var{stream} should never be an
+expression with side-effects.
 @end deftypefun
 
 @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})