diff mbox series

[6/9] pre-process: print variable argument macros correctly

Message ID 91253db3-6c8e-2b2f-0672-73b804b26ac2@ramsayjones.plus.com (mailing list archive)
State Mainlined, archived
Headers show
Series misc sparse patches | expand

Commit Message

Ramsay Jones Nov. 19, 2018, 8:51 p.m. UTC
The dump_macros() function fails to correctly output the definition of
macros that have a variable argument list. For example, the following
macros:

    #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
    #define apply(x,...) x(__VA_ARGS__)

are output like so:

    #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
    #define apply(x,__VA_ARGS__) x(__VA_ARGS__)

Add the code necessary to print the ellipsis in the argument list to the
dump_macros() function and add the above macros to the 'dump-macros.c'
test file.

Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
---
 pre-process.c                         | 11 ++++++++++-
 validation/preprocessor/dump-macros.c |  5 +++++
 2 files changed, 15 insertions(+), 1 deletion(-)

Comments

Luc Van Oostenryck Nov. 20, 2018, 12:06 a.m. UTC | #1
On Mon, Nov 19, 2018 at 08:51:33PM +0000, Ramsay Jones wrote:
> 
> The dump_macros() function fails to correctly output the definition of
> macros that have a variable argument list. For example, the following
> macros:
> 
>     #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
>     #define apply(x,...) x(__VA_ARGS__)
> 
> are output like so:
> 
>     #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
>     #define apply(x,__VA_ARGS__) x(__VA_ARGS__)
> 
> Add the code necessary to print the ellipsis in the argument list to the
> dump_macros() function and add the above macros to the 'dump-macros.c'
> test file.
> 
> Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
> ---
>  pre-process.c                         | 11 ++++++++++-
>  validation/preprocessor/dump-macros.c |  5 +++++
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/pre-process.c b/pre-process.c
> index 7b76c65..418b8ee 100644
> --- a/pre-process.c
> +++ b/pre-process.c
> @@ -2167,6 +2167,12 @@ struct token * preprocess(struct token *token)
>  	return token;
>  }
>  
> +static int is_VA_ARGS_token(struct token *token)
> +{
> +	return (token_type(token) == TOKEN_IDENT) &&
> +		(token->ident == &__VA_ARGS___ident);
> +}
> +
>  static void dump_macro(struct symbol *sym)
>  {
>  	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
> @@ -2182,7 +2188,10 @@ static void dump_macro(struct symbol *sym)
>  		for (; !eof_token(token); token = token->next) {
>  			if (token_type(token) == TOKEN_ARG_COUNT)
>  				continue;
> -			printf("%s%s", sep, show_token(token));
> +			if (is_VA_ARGS_token(token))
> +				printf("%s...", sep);
> +			else
> +				printf("%s%s", sep, show_token(token));

I'm wondering what is displayed by:
	show_ident(&__VA_ARGS___ident);

I would much prefer to adjust show_ident()/show_token() and keep
the code here generic.

-- Luc
Luc Van Oostenryck Nov. 21, 2018, 12:12 a.m. UTC | #2
On Tue, Nov 20, 2018 at 01:06:23AM +0100, Luc Van Oostenryck wrote:
> On Mon, Nov 19, 2018 at 08:51:33PM +0000, Ramsay Jones wrote:
> > 
> > The dump_macros() function fails to correctly output the definition of
> > macros that have a variable argument list. For example, the following
> > macros:
> > 
> >     #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
> >     #define apply(x,...) x(__VA_ARGS__)
> > 
> > are output like so:
> > 
> >     #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
> >     #define apply(x,__VA_ARGS__) x(__VA_ARGS__)
> > 
> > Add the code necessary to print the ellipsis in the argument list to the
> > dump_macros() function and add the above macros to the 'dump-macros.c'
> > test file.
> > 
> > Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
> > ---
> >  pre-process.c                         | 11 ++++++++++-
> >  validation/preprocessor/dump-macros.c |  5 +++++
> >  2 files changed, 15 insertions(+), 1 deletion(-)
> > 
> > diff --git a/pre-process.c b/pre-process.c
> > index 7b76c65..418b8ee 100644
> > --- a/pre-process.c
> > +++ b/pre-process.c
> > @@ -2167,6 +2167,12 @@ struct token * preprocess(struct token *token)
> >  	return token;
> >  }
> >  
> > +static int is_VA_ARGS_token(struct token *token)
> > +{
> > +	return (token_type(token) == TOKEN_IDENT) &&
> > +		(token->ident == &__VA_ARGS___ident);
> > +}
> > +
> >  static void dump_macro(struct symbol *sym)
> >  {
> >  	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
> > @@ -2182,7 +2188,10 @@ static void dump_macro(struct symbol *sym)
> >  		for (; !eof_token(token); token = token->next) {
> >  			if (token_type(token) == TOKEN_ARG_COUNT)
> >  				continue;
> > -			printf("%s%s", sep, show_token(token));
> > +			if (is_VA_ARGS_token(token))
> > +				printf("%s...", sep);
> > +			else
> > +				printf("%s%s", sep, show_token(token));
> 
> I'm wondering what is displayed by:
> 	show_ident(&__VA_ARGS___ident);
> 
> I would much prefer to adjust show_ident()/show_token() and keep
> the code here generic.

Mmmm, I looked at this one and what you've done here is the best.
I don't understand exactly why but for arguments the token
SPECIAL_ELLIPSIS is, at some stage, changed into a VA_ARGS ident.
This need then to be reversed when dumping the macros.

-- Luc
Ramsay Jones Nov. 21, 2018, 1:26 a.m. UTC | #3
On 21/11/2018 00:12, Luc Van Oostenryck wrote:
> On Tue, Nov 20, 2018 at 01:06:23AM +0100, Luc Van Oostenryck wrote:
>> On Mon, Nov 19, 2018 at 08:51:33PM +0000, Ramsay Jones wrote:
>>>
>>> The dump_macros() function fails to correctly output the definition of
>>> macros that have a variable argument list. For example, the following
>>> macros:
>>>
>>>     #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
>>>     #define apply(x,...) x(__VA_ARGS__)
>>>
>>> are output like so:
>>>
>>>     #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
>>>     #define apply(x,__VA_ARGS__) x(__VA_ARGS__)
>>>
>>> Add the code necessary to print the ellipsis in the argument list to the
>>> dump_macros() function and add the above macros to the 'dump-macros.c'
>>> test file.
>>>
>>> Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
>>> ---
>>>  pre-process.c                         | 11 ++++++++++-
>>>  validation/preprocessor/dump-macros.c |  5 +++++
>>>  2 files changed, 15 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/pre-process.c b/pre-process.c
>>> index 7b76c65..418b8ee 100644
>>> --- a/pre-process.c
>>> +++ b/pre-process.c
>>> @@ -2167,6 +2167,12 @@ struct token * preprocess(struct token *token)
>>>  	return token;
>>>  }
>>>  
>>> +static int is_VA_ARGS_token(struct token *token)
>>> +{
>>> +	return (token_type(token) == TOKEN_IDENT) &&
>>> +		(token->ident == &__VA_ARGS___ident);
>>> +}
>>> +
>>>  static void dump_macro(struct symbol *sym)
>>>  {
>>>  	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
>>> @@ -2182,7 +2188,10 @@ static void dump_macro(struct symbol *sym)
>>>  		for (; !eof_token(token); token = token->next) {
>>>  			if (token_type(token) == TOKEN_ARG_COUNT)
>>>  				continue;
>>> -			printf("%s%s", sep, show_token(token));
>>> +			if (is_VA_ARGS_token(token))
>>> +				printf("%s...", sep);
>>> +			else
>>> +				printf("%s%s", sep, show_token(token));
>>
>> I'm wondering what is displayed by:
>> 	show_ident(&__VA_ARGS___ident);
>>
>> I would much prefer to adjust show_ident()/show_token() and keep
>> the code here generic.
> 
> Mmmm, I looked at this one and what you've done here is the best.
> I don't understand exactly why but for arguments the token
> SPECIAL_ELLIPSIS is, at some stage, changed into a VA_ARGS ident.

Heh, I'm having a weird flashback! I don't quite remember the details,
but I was convinced the parse_arguments() (pre-process.c #1087) function
was wrong, but I got lost several times in the debugger, so gave up!

I thought a normal return would come from the condition at line 1123,
which would leave the SPECIAL_ELLIPSIS token alone, rather than from
the conditional at line 1143, which replaces it with VA_ARGS. ;-)

> This need then to be reversed when dumping the macros.

It is possible that SPECIAL_ELLIPSIS is not _always_ replaced with
VA_ARGS, and the above should still work. However, I may have given up
too easily. :)

ATB,
Ramsay Jones
Luc Van Oostenryck Nov. 21, 2018, 2:01 a.m. UTC | #4
On Wed, Nov 21, 2018 at 01:26:13AM +0000, Ramsay Jones wrote:
> 
> 
> On 21/11/2018 00:12, Luc Van Oostenryck wrote:
> > On Tue, Nov 20, 2018 at 01:06:23AM +0100, Luc Van Oostenryck wrote:
> >> On Mon, Nov 19, 2018 at 08:51:33PM +0000, Ramsay Jones wrote:
> >>>
> >>> The dump_macros() function fails to correctly output the definition of
> >>> macros that have a variable argument list. For example, the following
> >>> macros:
> >>>
> >>>     #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
> >>>     #define apply(x,...) x(__VA_ARGS__)
> >>>
> >>> are output like so:
> >>>
> >>>     #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
> >>>     #define apply(x,__VA_ARGS__) x(__VA_ARGS__)
> >>>
> >>> Add the code necessary to print the ellipsis in the argument list to the
> >>> dump_macros() function and add the above macros to the 'dump-macros.c'
> >>> test file.
> >>>
> >>> Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
> >>> ---
> >>>  pre-process.c                         | 11 ++++++++++-
> >>>  validation/preprocessor/dump-macros.c |  5 +++++
> >>>  2 files changed, 15 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/pre-process.c b/pre-process.c
> >>> index 7b76c65..418b8ee 100644
> >>> --- a/pre-process.c
> >>> +++ b/pre-process.c
> >>> @@ -2167,6 +2167,12 @@ struct token * preprocess(struct token *token)
> >>>  	return token;
> >>>  }
> >>>  
> >>> +static int is_VA_ARGS_token(struct token *token)
> >>> +{
> >>> +	return (token_type(token) == TOKEN_IDENT) &&
> >>> +		(token->ident == &__VA_ARGS___ident);
> >>> +}
> >>> +
> >>>  static void dump_macro(struct symbol *sym)
> >>>  {
> >>>  	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
> >>> @@ -2182,7 +2188,10 @@ static void dump_macro(struct symbol *sym)
> >>>  		for (; !eof_token(token); token = token->next) {
> >>>  			if (token_type(token) == TOKEN_ARG_COUNT)
> >>>  				continue;
> >>> -			printf("%s%s", sep, show_token(token));
> >>> +			if (is_VA_ARGS_token(token))
> >>> +				printf("%s...", sep);
> >>> +			else
> >>> +				printf("%s%s", sep, show_token(token));
> >>
> >> I'm wondering what is displayed by:
> >> 	show_ident(&__VA_ARGS___ident);
> >>
> >> I would much prefer to adjust show_ident()/show_token() and keep
> >> the code here generic.
> > 
> > Mmmm, I looked at this one and what you've done here is the best.
> > I don't understand exactly why but for arguments the token
> > SPECIAL_ELLIPSIS is, at some stage, changed into a VA_ARGS ident.
> 
> Heh, I'm having a weird flashback! I don't quite remember the details,
> but I was convinced the parse_arguments() (pre-process.c #1087) function
> was wrong, but I got lost several times in the debugger, so gave up!
> 
> I thought a normal return would come from the condition at line 1123,
> which would leave the SPECIAL_ELLIPSIS token alone, rather than from
> the conditional at line 1143, which replaces it with VA_ARGS. ;-)
> 
> It is possible that SPECIAL_ELLIPSIS is not _always_ replaced with
> VA_ARGS, and the above should still work. However, I may have given up
> too easily. :)

Yes, but this condition is only reached if you have something like:
	#define m(x ...)
and then either it's an error (no ending ')' ) or the ellipsis is
replaced by TOKEN_ARG_COUNT. OTOH, the condition at line 1143 is
reached when you have something like:
	#define m(x,...)
or
	#define m(...)

So, I think the function is correct and the ellipses are always
replaced in non-erroneous cases (and the replacement is needed
for current processing).

-- Luc
Ramsay Jones Nov. 21, 2018, 7:38 p.m. UTC | #5
On 21/11/2018 02:01, Luc Van Oostenryck wrote:
> On Wed, Nov 21, 2018 at 01:26:13AM +0000, Ramsay Jones wrote:
>>
>>
>> On 21/11/2018 00:12, Luc Van Oostenryck wrote:
>>> On Tue, Nov 20, 2018 at 01:06:23AM +0100, Luc Van Oostenryck wrote:
>>>> On Mon, Nov 19, 2018 at 08:51:33PM +0000, Ramsay Jones wrote:
>>>>>
>>>>> The dump_macros() function fails to correctly output the definition of
>>>>> macros that have a variable argument list. For example, the following
>>>>> macros:
>>>>>
>>>>>     #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
>>>>>     #define apply(x,...) x(__VA_ARGS__)
>>>>>
>>>>> are output like so:
>>>>>
>>>>>     #define unlocks(__VA_ARGS__) annotate(unlock_func(__VA_ARGS__))
>>>>>     #define apply(x,__VA_ARGS__) x(__VA_ARGS__)
>>>>>
>>>>> Add the code necessary to print the ellipsis in the argument list to the
>>>>> dump_macros() function and add the above macros to the 'dump-macros.c'
>>>>> test file.
>>>>>
>>>>> Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
>>>>> ---
>>>>>  pre-process.c                         | 11 ++++++++++-
>>>>>  validation/preprocessor/dump-macros.c |  5 +++++
>>>>>  2 files changed, 15 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/pre-process.c b/pre-process.c
>>>>> index 7b76c65..418b8ee 100644
>>>>> --- a/pre-process.c
>>>>> +++ b/pre-process.c
>>>>> @@ -2167,6 +2167,12 @@ struct token * preprocess(struct token *token)
>>>>>  	return token;
>>>>>  }
>>>>>  
>>>>> +static int is_VA_ARGS_token(struct token *token)
>>>>> +{
>>>>> +	return (token_type(token) == TOKEN_IDENT) &&
>>>>> +		(token->ident == &__VA_ARGS___ident);
>>>>> +}
>>>>> +
>>>>>  static void dump_macro(struct symbol *sym)
>>>>>  {
>>>>>  	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
>>>>> @@ -2182,7 +2188,10 @@ static void dump_macro(struct symbol *sym)
>>>>>  		for (; !eof_token(token); token = token->next) {
>>>>>  			if (token_type(token) == TOKEN_ARG_COUNT)
>>>>>  				continue;
>>>>> -			printf("%s%s", sep, show_token(token));
>>>>> +			if (is_VA_ARGS_token(token))
>>>>> +				printf("%s...", sep);
>>>>> +			else
>>>>> +				printf("%s%s", sep, show_token(token));
>>>>
>>>> I'm wondering what is displayed by:
>>>> 	show_ident(&__VA_ARGS___ident);
>>>>
>>>> I would much prefer to adjust show_ident()/show_token() and keep
>>>> the code here generic.
>>>
>>> Mmmm, I looked at this one and what you've done here is the best.
>>> I don't understand exactly why but for arguments the token
>>> SPECIAL_ELLIPSIS is, at some stage, changed into a VA_ARGS ident.
>>
>> Heh, I'm having a weird flashback! I don't quite remember the details,
>> but I was convinced the parse_arguments() (pre-process.c #1087) function
>> was wrong, but I got lost several times in the debugger, so gave up!
>>
>> I thought a normal return would come from the condition at line 1123,
>> which would leave the SPECIAL_ELLIPSIS token alone, rather than from
>> the conditional at line 1143, which replaces it with VA_ARGS. ;-)
>>
>> It is possible that SPECIAL_ELLIPSIS is not _always_ replaced with
>> VA_ARGS, and the above should still work. However, I may have given up
>> too easily. :)
> 
> Yes, but this condition is only reached if you have something like:
> 	#define m(x ...)
> and then either it's an error (no ending ')' ) or the ellipsis is
> replaced by TOKEN_ARG_COUNT. OTOH, the condition at line 1143 is
> reached when you have something like:
> 	#define m(x,...)
> or
> 	#define m(...)
> 
> So, I think the function is correct and the ellipses are always
> replaced in non-erroneous cases (and the replacement is needed
> for current processing).

Ah, yes, you are (of course) correct. Having been prompted, I now
remember that the penny dropped when I was trying to follow a (cut-
down) version of one of the preprocessorXX.c tests in the debugger.

I was still a little concerned about the discrepancy in the token
mangling and made a note to come back and look at that again (which
I haven't done, obviously!). However, even if the dump-macros code
would have been presented with either token type, the (new) code
can handle both, so ...

I am a little busy at the moment, but I will try to send out a new
version of the patches soon. Well, I don't quite know what to do
about patch #8. Shall we just drop that one for now (I can un-comment
the SPARSE_FLAGS in my config.mak file again), or do you have an
idea to improve the implementation of that patch?

ATB,
Ramsay Jones
Luc Van Oostenryck Nov. 22, 2018, 2:47 a.m. UTC | #6
On Wed, Nov 21, 2018 at 07:38:11PM +0000, Ramsay Jones wrote:
> 
> I am a little busy at the moment, but I will try to send out a new
> version of the patches soon.

No worries.
I can take #1 & #2 as is and I would like to take #9 quickly.
#3-#6 don't need changes IIRC. I would like a small change in #7
but it can tweak it myself (I've more time now than I had in the
past weeks and much probably more than you have now).

> Well, I don't quite know what to do
> about patch #8. Shall we just drop that one for now (I can un-comment
> the SPARSE_FLAGS in my config.mak file again), or do you have an
> idea to improve the implementation of that patch?

Yes, this #8 is annoying. I'll think a bit about what can be done.

Best regards,
-- Luc
diff mbox series

Patch

diff --git a/pre-process.c b/pre-process.c
index 7b76c65..418b8ee 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -2167,6 +2167,12 @@  struct token * preprocess(struct token *token)
 	return token;
 }
 
+static int is_VA_ARGS_token(struct token *token)
+{
+	return (token_type(token) == TOKEN_IDENT) &&
+		(token->ident == &__VA_ARGS___ident);
+}
+
 static void dump_macro(struct symbol *sym)
 {
 	int nargs = sym->arglist ? sym->arglist->count.normal : 0;
@@ -2182,7 +2188,10 @@  static void dump_macro(struct symbol *sym)
 		for (; !eof_token(token); token = token->next) {
 			if (token_type(token) == TOKEN_ARG_COUNT)
 				continue;
-			printf("%s%s", sep, show_token(token));
+			if (is_VA_ARGS_token(token))
+				printf("%s...", sep);
+			else
+				printf("%s%s", sep, show_token(token));
 			args[narg++] = token;
 			sep = ",";
 		}
diff --git a/validation/preprocessor/dump-macros.c b/validation/preprocessor/dump-macros.c
index f8983d8..6940a20 100644
--- a/validation/preprocessor/dump-macros.c
+++ b/validation/preprocessor/dump-macros.c
@@ -9,6 +9,9 @@ 
 
 #define STRING(x) #x
 #define CONCAT(x,y) x ## y
+
+#define unlocks(...) annotate(unlock_func(__VA_ARGS__))
+#define apply(x,...) x(__VA_ARGS__)
 /*
  * check-name: dump-macros
  * check-command: sparse -E -dD -DIJK=ijk -UNDEF -UNYDEF $file
@@ -20,4 +23,6 @@  check-output-contains: #define DEF xyz
 check-output-contains: #define NYDEF ydef
 check-output-contains: #define STRING(x) #x
 check-output-contains: #define CONCAT(x,y) x ## y
+check-output-contains: #define unlocks(...) annotate(unlock_func(__VA_ARGS__))
+check-output-contains: #define apply(x,...) x(__VA_ARGS__)
  */