diff mbox

[v3,3/3] kconfig: Print reverse dependencies in groups

Message ID 20180218110702.GA26185@example.com (mailing list archive)
State New, archived
Headers show

Commit Message

Eugeniu Rosca Feb. 18, 2018, 11:07 a.m. UTC
On Sat, Feb 17, 2018 at 05:55:01PM +0100, Ulf Magnusson wrote:
> On Sat, Feb 17, 2018 at 3:05 AM, Eugeniu Rosca <roscaeugeniu@gmail.com> wrote:
> > From: Eugeniu Rosca <erosca@de.adit-jv.com>
> >
> > Assuming commit 617aebe6a97e ("Merge tag 'usercopy-v4.16-rc1' of
> > git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux"), ARCH=arm64
> > and vanilla arm64 defconfig, here is the top 10 CONFIG options with
> > the highest amount of top level "||" sub-expressions/tokens that make
> > up the final "{Selected,Implied} by" reverse dependency expression.
> >
> > | Config                        | Revdep all | Revdep ![=n] |
> > |-------------------------------|------------|--------------|
> > | REGMAP_I2C                    | 212        | 9            |
> > | CRC32                         | 167        | 25           |
> > | FW_LOADER                     | 128        | 5            |
> > | MFD_CORE                      | 124        | 9            |
> > | FB_CFB_IMAGEBLIT              | 114        | 2            |
> > | FB_CFB_COPYAREA               | 111        | 2            |
> > | FB_CFB_FILLRECT               | 110        | 2            |
> > | SND_PCM                       | 103        | 2            |
> > | CRYPTO_HASH                   | 87         | 19           |
> > | WATCHDOG_CORE                 | 86         | 6            |
> >
> > The story behind the above is that users need to visually
> > review/evaluate 212 expressions which *potentially* select REGMAP_I2C
> > in order to identify the expressions which *actually* select REGMAP_I2C,
> > for a particular ARCH and for a particular defconfig used.
> >
> > To make this experience smoother, change the way reverse dependencies
> > are displayed to the user from [1] to [2].
> >
> > [1] Old representation of reverse dependencies for DMA_ENGINE_RAID:
> >   Selected by:
> >   - AMCC_PPC440SPE_ADMA [=n] && DMADEVICES [=y] && (440SPe || 440SP)
> >   - BCM_SBA_RAID [=m] && DMADEVICES [=y] && (ARM64 [=y] || ...
> >   - FSL_RAID [=n] && DMADEVICES [=y] && FSL_SOC && ...
> >   - INTEL_IOATDMA [=n] && DMADEVICES [=y] && PCI [=y] && X86_64
> >   - MV_XOR [=n] && DMADEVICES [=y] && (PLAT_ORION || ARCH_MVEBU [=y] ...
> >   - MV_XOR_V2 [=y] && DMADEVICES [=y] && ARM64 [=y]
> >   - XGENE_DMA [=n] && DMADEVICES [=y] && (ARCH_XGENE [=y] || ...
> >   - DMATEST [=n] && DMADEVICES [=y] && DMA_ENGINE [=y]
> >
> > [2] New representation of reverse dependencies for DMA_ENGINE_RAID:
> >   Selected by [y]:
> >   - MV_XOR_V2 [=y] && DMADEVICES [=y] && ARM64 [=y]
> >   Selected by [m]:
> >   - BCM_SBA_RAID [=m] && DMADEVICES [=y] && (ARM64 [=y] || ...
> >   Selected by [n]:
> >   - AMCC_PPC440SPE_ADMA [=n] && DMADEVICES [=y] && (440SPe || ...
> >   - FSL_RAID [=n] && DMADEVICES [=y] && FSL_SOC && ...
> >   - INTEL_IOATDMA [=n] && DMADEVICES [=y] && PCI [=y] && X86_64
> >   - MV_XOR [=n] && DMADEVICES [=y] && (PLAT_ORION || ARCH_MVEBU [=y] ...
> >   - XGENE_DMA [=n] && DMADEVICES [=y] && (ARCH_XGENE [=y] || ...
> >   - DMATEST [=n] && DMADEVICES [=y] && DMA_ENGINE [=y]
> >
> > Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com>
> > ---
> >  scripts/kconfig/expr.c      | 59 ++++++++++++++++++++++++++++++++++++++++++++-
> >  scripts/kconfig/expr.h      |  4 +++
> >  scripts/kconfig/lkc_proto.h |  1 +
> >  scripts/kconfig/menu.c      | 37 ++++++++++++++++++++--------
> >  4 files changed, 90 insertions(+), 11 deletions(-)
> >
> > diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
> > index c610cb14284f..48b99371d276 100644
> > --- a/scripts/kconfig/expr.c
> > +++ b/scripts/kconfig/expr.c
> > @@ -1213,6 +1213,18 @@ __expr_print(struct expr *e,
> >                         case PRINT_REVDEP_ALL:
> >                                 expr_print_newline(e, fn, data, E_OR);
> >                                 break;
> > +                       case PRINT_REVDEP_YES:
> > +                               if (expr_calc_value(e) == yes)
> > +                                       expr_print_newline(e, fn, data, E_OR);
> > +                               break;
> > +                       case PRINT_REVDEP_MOD:
> > +                               if (expr_calc_value(e) == mod)
> > +                                       expr_print_newline(e, fn, data, E_OR);
> > +                               break;
> > +                       case PRINT_REVDEP_NO:
> > +                               if (expr_calc_value(e) == no)
> > +                                       expr_print_newline(e, fn, data, E_OR);
> > +                               break;
> 
> Perhaps this logic could be moved into expr_print_newline() (which
> could be renamed to something like expr_print_select() in that case).
> Could have it take 'enum print_type' as an argument.

If expr_print_newline is renamed to expr_print_{select,revdep}, then
I still face the need of expr_print_newline. So, I kept the *newline()
function in place and came up with below solution to aggregate
duplicated code. Please, let me know if it looks OK to you (btw, it
creates a slightly higher --stat compared to current solution).


> 
> > +       PRINT_REVDEP_YES,
> > +       PRINT_REVDEP_MOD,
> > +       PRINT_REVDEP_NO,
> >  };
> >
> >  union expr_data {
> > @@ -316,6 +319,7 @@ void expr_fprint(struct expr *e, FILE *out);
> >  struct gstr; /* forward */
> >  void expr_gstr_print(struct expr *e, struct gstr *gs);
> >  void expr_gstr_print_revdep(struct expr *e, struct gstr *gs, enum print_type t);
> > +bool expr_revdep_contains(struct expr *e, tristate val);
> >
> >  static inline int expr_is_yes(struct expr *e)
> >  {
> > diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
> > index 9dc8abfb1dc3..69ed1477e4ef 100644
> > --- a/scripts/kconfig/lkc_proto.h
> > +++ b/scripts/kconfig/lkc_proto.h
> > @@ -25,6 +25,7 @@ bool menu_has_help(struct menu *menu);
> >  const char * menu_get_help(struct menu *menu);
> >  struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
> >  void menu_get_ext_help(struct menu *menu, struct gstr *help);
> > +void get_revdep_by_type(struct expr *e, char *s, struct gstr *r);
> >
> >  /* symbol.c */
> >  extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
> > diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
> > index 5b8edba105f2..d13ffa69d65b 100644
> > --- a/scripts/kconfig/menu.c
> > +++ b/scripts/kconfig/menu.c
> > @@ -790,6 +790,31 @@ static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
> >                 str_append(r, "\n");
> >  }
> >
> > +void get_revdep_by_type(struct expr *e, char *s, struct gstr *r)
> > +{
> > +       if (!e)
> > +               return;
> > +
> > +       if (expr_revdep_contains(e, yes)) {
> > +               str_append(r, s);
> > +               str_append(r, _(" [y]:"));
> > +               expr_gstr_print_revdep(e, r, PRINT_REVDEP_YES);
> > +               str_append(r, "\n");
> > +       }
> > +       if (expr_revdep_contains(e, mod)) {
> > +               str_append(r, s);
> > +               str_append(r, _(" [m]:"));
> > +               expr_gstr_print_revdep(e, r, PRINT_REVDEP_MOD);
> > +               str_append(r, "\n");
> > +       }
> > +       if (expr_revdep_contains(e, no)) {
> > +               str_append(r, s);
> > +               str_append(r, _(" [n]:"));
> > +               expr_gstr_print_revdep(e, r, PRINT_REVDEP_NO);
> > +               str_append(r, "\n");
> > +       }
> > +}
> 
> Those _() are for gettext btw. Not sure those strings need
> translations (or if anyone is translating Kconfig), so I think they
> could be removed here.

No problem. I can remove them :)

> 
> > +
> >  /*
> >   * head is optional and may be NULL
> >   */
> > @@ -826,18 +851,10 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
> >         }
> >
> >         get_symbol_props_str(r, sym, P_SELECT, _("  Selects: "));
> > -       if (sym->rev_dep.expr) {
> > -               str_append(r, _("  Selected by: "));
> > -               expr_gstr_print_revdep(sym->rev_dep.expr, r, PRINT_REVDEP_ALL);
> > -               str_append(r, "\n");
> > -       }
> > +       get_revdep_by_type(sym->rev_dep.expr, "  Selected by", r);
> >
> >         get_symbol_props_str(r, sym, P_IMPLY, _("  Implies: "));
> > -       if (sym->implied.expr) {
> > -               str_append(r, _("  Implied by: "));
> > -               expr_gstr_print_revdep(sym->implied.expr, r, PRINT_REVDEP_ALL);
> > -               str_append(r, "\n");
> > -       }
> > +       get_revdep_by_type(sym->implied.expr, "  Implied by", r);
> >
> >         str_append(r, "\n\n");
> >  }
> > --
> > 2.16.1
> >
> 
> Looks like a very nice patchset in general to me.

After getting your feedback/preference on the above, I will
hopefully be able to push v4. Thanks for the reviewing effort!

> Cheers,
> Ulf

Regards,
Eugeniu.
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Ulf Magnusson Feb. 18, 2018, 1:02 p.m. UTC | #1
On Sun, Feb 18, 2018 at 12:07:02PM +0100, Eugeniu Rosca wrote:
> If expr_print_newline is renamed to expr_print_{select,revdep}, then
> I still face the need of expr_print_newline. So, I kept the *newline()
> function in place and came up with below solution to aggregate
> duplicated code. Please, let me know if it looks OK to you (btw, it
> creates a slightly higher --stat compared to current solution).
> 
> diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
> index 48b99371d276..a6316e5681d9 100644
> --- a/scripts/kconfig/expr.c
> +++ b/scripts/kconfig/expr.c
> @@ -1189,6 +1189,34 @@ expr_print_newline(struct expr *e,
>  	expr_print(e, fn, data, prevtoken);
>  }
>  
> +static void
> +expr_print_revdep(struct expr *e,
> +		  void (*fn)(void *, struct symbol *, const char *),
> +		  void *data,
> +		  int prevtoken,
> +		  enum print_type type)
> +{
> +	switch (type) {
> +	case PRINT_REVDEP_ALL:
> +		expr_print_newline(e, fn, data, prevtoken);
> +		break;
> +	case PRINT_REVDEP_YES:
> +		if (expr_calc_value(e) == yes)
> +			expr_print_newline(e, fn, data, prevtoken);
> +		break;
> +	case PRINT_REVDEP_MOD:
> +		if (expr_calc_value(e) == mod)
> +			expr_print_newline(e, fn, data, prevtoken);
> +		break;
> +	case PRINT_REVDEP_NO:
> +		if (expr_calc_value(e) == no)
> +			expr_print_newline(e, fn, data, prevtoken);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +

I think it's fine to have a separate expr_print_newline() function
still. Getting rid of the repetition still makes it more readable to me.

Maybe you could do something like this if you want to eliminate
expr_print_newline() though. AFAICS, it isn't used outside
expr_print_revdep().

	static void
	expr_print_revdep(struct expr *e,
			  void (*fn)(void *, struct symbol *, const char *),
			  void *data,
			  int prevtoken,
			  enum print_type type)
	{
		if (type == PRINT_REVDEP_ALL                              ||
		    type == PRINT_REVDEP_YES && expr_calc_value(e) == yes ||
		    type == PRINT_REVDEP_MOD && expr_calc_value(e) == mod ||
		    type == PRINT_REVDEP_NO  && expr_calc_value(e) == no) {

			fn(data, NULL, "\n - ");
			expr_print(e, fn, data, prevtoken);
		}
	}


Could turn that into a switch over 'type' and set a 'print_revdep' flag
which is checked at the end too, if you'd prefer that:

	switch (type) {
	...
	case PRINT_REVDEP_YES:
		print_revdep = (expr_calc_value(e) == yes);
		break;
	...
	}

	if (print_revdep) {
		fn(data, NULL, "\n - ");
		expr_print(e, fn, data, prevtoken);
	}


Or return early:

	case PRINT_REVDEP_YES:
		if (expr_calc_value(e) != yes)
			return;
		break;
	...
	}

	fn(data, NULL, "\n - ");
	expr_print(e, fn, data, prevtoken);


The original version is already fine by me though. The 'if' version
seems pretty direct too.

Cheers,
Ulf
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ulf Magnusson Feb. 18, 2018, 1:19 p.m. UTC | #2
On Sun, Feb 18, 2018 at 2:02 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> On Sun, Feb 18, 2018 at 12:07:02PM +0100, Eugeniu Rosca wrote:
>> If expr_print_newline is renamed to expr_print_{select,revdep}, then
>> I still face the need of expr_print_newline. So, I kept the *newline()
>> function in place and came up with below solution to aggregate
>> duplicated code. Please, let me know if it looks OK to you (btw, it
>> creates a slightly higher --stat compared to current solution).
>>
>> diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
>> index 48b99371d276..a6316e5681d9 100644
>> --- a/scripts/kconfig/expr.c
>> +++ b/scripts/kconfig/expr.c
>> @@ -1189,6 +1189,34 @@ expr_print_newline(struct expr *e,
>>       expr_print(e, fn, data, prevtoken);
>>  }
>>
>> +static void
>> +expr_print_revdep(struct expr *e,
>> +               void (*fn)(void *, struct symbol *, const char *),
>> +               void *data,
>> +               int prevtoken,
>> +               enum print_type type)
>> +{
>> +     switch (type) {
>> +     case PRINT_REVDEP_ALL:
>> +             expr_print_newline(e, fn, data, prevtoken);
>> +             break;
>> +     case PRINT_REVDEP_YES:
>> +             if (expr_calc_value(e) == yes)
>> +                     expr_print_newline(e, fn, data, prevtoken);
>> +             break;
>> +     case PRINT_REVDEP_MOD:
>> +             if (expr_calc_value(e) == mod)
>> +                     expr_print_newline(e, fn, data, prevtoken);
>> +             break;
>> +     case PRINT_REVDEP_NO:
>> +             if (expr_calc_value(e) == no)
>> +                     expr_print_newline(e, fn, data, prevtoken);
>> +             break;
>> +     default:
>> +             break;
>> +     }
>> +}
>> +
>
> I think it's fine to have a separate expr_print_newline() function
> still. Getting rid of the repetition still makes it more readable to me.
>
> Maybe you could do something like this if you want to eliminate
> expr_print_newline() though. AFAICS, it isn't used outside
> expr_print_revdep().
>
>         static void
>         expr_print_revdep(struct expr *e,
>                           void (*fn)(void *, struct symbol *, const char *),
>                           void *data,
>                           int prevtoken,
>                           enum print_type type)
>         {
>                 if (type == PRINT_REVDEP_ALL                              ||
>                     type == PRINT_REVDEP_YES && expr_calc_value(e) == yes ||
>                     type == PRINT_REVDEP_MOD && expr_calc_value(e) == mod ||
>                     type == PRINT_REVDEP_NO  && expr_calc_value(e) == no) {
>
>                         fn(data, NULL, "\n - ");
>                         expr_print(e, fn, data, prevtoken);
>                 }
>         }
>
>
> Could turn that into a switch over 'type' and set a 'print_revdep' flag
> which is checked at the end too, if you'd prefer that:
>
>         switch (type) {
>         ...
>         case PRINT_REVDEP_YES:
>                 print_revdep = (expr_calc_value(e) == yes);
>                 break;
>         ...
>         }
>
>         if (print_revdep) {
>                 fn(data, NULL, "\n - ");
>                 expr_print(e, fn, data, prevtoken);
>         }
>
>
> Or return early:
>
>         case PRINT_REVDEP_YES:
>                 if (expr_calc_value(e) != yes)
>                         return;
>                 break;
>         ...
>         }
>
>         fn(data, NULL, "\n - ");
>         expr_print(e, fn, data, prevtoken);
>
>
> The original version is already fine by me though. The 'if' version
> seems pretty direct too.
>
> Cheers,
> Ulf

Hmm... was thinking that you could get rid of 'print_type' and just
pass a tristate value for a moment too. There's PRINT_NORMAL and
PRINT_REVDEP_ALL to deal with as well though, so it'd get messy.

Cheers,
Ulf
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ulf Magnusson Feb. 18, 2018, 1:35 p.m. UTC | #3
On Sun, Feb 18, 2018 at 2:19 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> On Sun, Feb 18, 2018 at 2:02 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
>> On Sun, Feb 18, 2018 at 12:07:02PM +0100, Eugeniu Rosca wrote:
>>> If expr_print_newline is renamed to expr_print_{select,revdep}, then
>>> I still face the need of expr_print_newline. So, I kept the *newline()
>>> function in place and came up with below solution to aggregate
>>> duplicated code. Please, let me know if it looks OK to you (btw, it
>>> creates a slightly higher --stat compared to current solution).
>>>
>>> diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
>>> index 48b99371d276..a6316e5681d9 100644
>>> --- a/scripts/kconfig/expr.c
>>> +++ b/scripts/kconfig/expr.c
>>> @@ -1189,6 +1189,34 @@ expr_print_newline(struct expr *e,
>>>       expr_print(e, fn, data, prevtoken);
>>>  }
>>>
>>> +static void
>>> +expr_print_revdep(struct expr *e,
>>> +               void (*fn)(void *, struct symbol *, const char *),
>>> +               void *data,
>>> +               int prevtoken,
>>> +               enum print_type type)
>>> +{
>>> +     switch (type) {
>>> +     case PRINT_REVDEP_ALL:
>>> +             expr_print_newline(e, fn, data, prevtoken);
>>> +             break;
>>> +     case PRINT_REVDEP_YES:
>>> +             if (expr_calc_value(e) == yes)
>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>> +             break;
>>> +     case PRINT_REVDEP_MOD:
>>> +             if (expr_calc_value(e) == mod)
>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>> +             break;
>>> +     case PRINT_REVDEP_NO:
>>> +             if (expr_calc_value(e) == no)
>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>> +             break;
>>> +     default:
>>> +             break;
>>> +     }
>>> +}
>>> +
>>
>> I think it's fine to have a separate expr_print_newline() function
>> still. Getting rid of the repetition still makes it more readable to me.
>>
>> Maybe you could do something like this if you want to eliminate
>> expr_print_newline() though. AFAICS, it isn't used outside
>> expr_print_revdep().
>>
>>         static void
>>         expr_print_revdep(struct expr *e,
>>                           void (*fn)(void *, struct symbol *, const char *),
>>                           void *data,
>>                           int prevtoken,
>>                           enum print_type type)
>>         {
>>                 if (type == PRINT_REVDEP_ALL                              ||
>>                     type == PRINT_REVDEP_YES && expr_calc_value(e) == yes ||
>>                     type == PRINT_REVDEP_MOD && expr_calc_value(e) == mod ||
>>                     type == PRINT_REVDEP_NO  && expr_calc_value(e) == no) {
>>
>>                         fn(data, NULL, "\n - ");
>>                         expr_print(e, fn, data, prevtoken);
>>                 }
>>         }
>>
>>
>> Could turn that into a switch over 'type' and set a 'print_revdep' flag
>> which is checked at the end too, if you'd prefer that:
>>
>>         switch (type) {
>>         ...
>>         case PRINT_REVDEP_YES:
>>                 print_revdep = (expr_calc_value(e) == yes);
>>                 break;
>>         ...
>>         }
>>
>>         if (print_revdep) {
>>                 fn(data, NULL, "\n - ");
>>                 expr_print(e, fn, data, prevtoken);
>>         }
>>
>>
>> Or return early:
>>
>>         case PRINT_REVDEP_YES:
>>                 if (expr_calc_value(e) != yes)
>>                         return;
>>                 break;
>>         ...
>>         }
>>
>>         fn(data, NULL, "\n - ");
>>         expr_print(e, fn, data, prevtoken);
>>
>>
>> The original version is already fine by me though. The 'if' version
>> seems pretty direct too.
>>
>> Cheers,
>> Ulf
>
> Hmm... was thinking that you could get rid of 'print_type' and just
> pass a tristate value for a moment too. There's PRINT_NORMAL and
> PRINT_REVDEP_ALL to deal with as well though, so it'd get messy.
>
> Cheers,
> Ulf

One last bikeshedding: Could factor out just the check into a function
and do something like this in __expr_print():

        if (select_has_type(e, type))
                expr_print_newline(e, fn, data, prevtoken);

Having a function that's just one big 'if' feels slightly silly,
though it's not horrible here either IMO.

Cheers,
Ulf
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ulf Magnusson Feb. 18, 2018, 1:40 p.m. UTC | #4
On Sun, Feb 18, 2018 at 2:35 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> On Sun, Feb 18, 2018 at 2:19 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
>> On Sun, Feb 18, 2018 at 2:02 PM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
>>> On Sun, Feb 18, 2018 at 12:07:02PM +0100, Eugeniu Rosca wrote:
>>>> If expr_print_newline is renamed to expr_print_{select,revdep}, then
>>>> I still face the need of expr_print_newline. So, I kept the *newline()
>>>> function in place and came up with below solution to aggregate
>>>> duplicated code. Please, let me know if it looks OK to you (btw, it
>>>> creates a slightly higher --stat compared to current solution).
>>>>
>>>> diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
>>>> index 48b99371d276..a6316e5681d9 100644
>>>> --- a/scripts/kconfig/expr.c
>>>> +++ b/scripts/kconfig/expr.c
>>>> @@ -1189,6 +1189,34 @@ expr_print_newline(struct expr *e,
>>>>       expr_print(e, fn, data, prevtoken);
>>>>  }
>>>>
>>>> +static void
>>>> +expr_print_revdep(struct expr *e,
>>>> +               void (*fn)(void *, struct symbol *, const char *),
>>>> +               void *data,
>>>> +               int prevtoken,
>>>> +               enum print_type type)
>>>> +{
>>>> +     switch (type) {
>>>> +     case PRINT_REVDEP_ALL:
>>>> +             expr_print_newline(e, fn, data, prevtoken);
>>>> +             break;
>>>> +     case PRINT_REVDEP_YES:
>>>> +             if (expr_calc_value(e) == yes)
>>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>>> +             break;
>>>> +     case PRINT_REVDEP_MOD:
>>>> +             if (expr_calc_value(e) == mod)
>>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>>> +             break;
>>>> +     case PRINT_REVDEP_NO:
>>>> +             if (expr_calc_value(e) == no)
>>>> +                     expr_print_newline(e, fn, data, prevtoken);
>>>> +             break;
>>>> +     default:
>>>> +             break;
>>>> +     }
>>>> +}
>>>> +
>>>
>>> I think it's fine to have a separate expr_print_newline() function
>>> still. Getting rid of the repetition still makes it more readable to me.
>>>
>>> Maybe you could do something like this if you want to eliminate
>>> expr_print_newline() though. AFAICS, it isn't used outside
>>> expr_print_revdep().
>>>
>>>         static void
>>>         expr_print_revdep(struct expr *e,
>>>                           void (*fn)(void *, struct symbol *, const char *),
>>>                           void *data,
>>>                           int prevtoken,
>>>                           enum print_type type)
>>>         {
>>>                 if (type == PRINT_REVDEP_ALL                              ||
>>>                     type == PRINT_REVDEP_YES && expr_calc_value(e) == yes ||
>>>                     type == PRINT_REVDEP_MOD && expr_calc_value(e) == mod ||
>>>                     type == PRINT_REVDEP_NO  && expr_calc_value(e) == no) {
>>>
>>>                         fn(data, NULL, "\n - ");
>>>                         expr_print(e, fn, data, prevtoken);
>>>                 }
>>>         }
>>>
>>>
>>> Could turn that into a switch over 'type' and set a 'print_revdep' flag
>>> which is checked at the end too, if you'd prefer that:
>>>
>>>         switch (type) {
>>>         ...
>>>         case PRINT_REVDEP_YES:
>>>                 print_revdep = (expr_calc_value(e) == yes);
>>>                 break;
>>>         ...
>>>         }
>>>
>>>         if (print_revdep) {
>>>                 fn(data, NULL, "\n - ");
>>>                 expr_print(e, fn, data, prevtoken);
>>>         }
>>>
>>>
>>> Or return early:
>>>
>>>         case PRINT_REVDEP_YES:
>>>                 if (expr_calc_value(e) != yes)
>>>                         return;
>>>                 break;
>>>         ...
>>>         }
>>>
>>>         fn(data, NULL, "\n - ");
>>>         expr_print(e, fn, data, prevtoken);
>>>
>>>
>>> The original version is already fine by me though. The 'if' version
>>> seems pretty direct too.
>>>
>>> Cheers,
>>> Ulf
>>
>> Hmm... was thinking that you could get rid of 'print_type' and just
>> pass a tristate value for a moment too. There's PRINT_NORMAL and
>> PRINT_REVDEP_ALL to deal with as well though, so it'd get messy.
>>
>> Cheers,
>> Ulf
>
> One last bikeshedding: Could factor out just the check into a function
> and do something like this in __expr_print():
>
>         if (select_has_type(e, type))
>                 expr_print_newline(e, fn, data, prevtoken);
>
> Having a function that's just one big 'if' feels slightly silly,
> though it's not horrible here either IMO.

Referring to this version that is:

        static void
        expr_print_revdep(struct expr *e,
                          void (*fn)(void *, struct symbol *, const char *),
                          void *data,
                          int prevtoken,
                          enum print_type type)
        {
                if (type == PRINT_REVDEP_ALL                              ||
                    type == PRINT_REVDEP_YES && expr_calc_value(e) == yes ||
                    type == PRINT_REVDEP_MOD && expr_calc_value(e) == mod ||
                    type == PRINT_REVDEP_NO  && expr_calc_value(e) == no) {

                        fn(data, NULL, "\n - ");
                        expr_print(e, fn, data, prevtoken);
                }
        }

Cheers,
Ulf
--
To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 48b99371d276..a6316e5681d9 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1189,6 +1189,34 @@  expr_print_newline(struct expr *e,
 	expr_print(e, fn, data, prevtoken);
 }
 
+static void
+expr_print_revdep(struct expr *e,
+		  void (*fn)(void *, struct symbol *, const char *),
+		  void *data,
+		  int prevtoken,
+		  enum print_type type)
+{
+	switch (type) {
+	case PRINT_REVDEP_ALL:
+		expr_print_newline(e, fn, data, prevtoken);
+		break;
+	case PRINT_REVDEP_YES:
+		if (expr_calc_value(e) == yes)
+			expr_print_newline(e, fn, data, prevtoken);
+		break;
+	case PRINT_REVDEP_MOD:
+		if (expr_calc_value(e) == mod)
+			expr_print_newline(e, fn, data, prevtoken);
+		break;
+	case PRINT_REVDEP_NO:
+		if (expr_calc_value(e) == no)
+			expr_print_newline(e, fn, data, prevtoken);
+		break;
+	default:
+		break;
+	}
+}
+
 static void
 __expr_print(struct expr *e,
 	     void (*fn)(void *, struct symbol *, const char *),
@@ -1211,21 +1239,10 @@  __expr_print(struct expr *e,
 				fn(data, e->left.sym, e->left.sym->name);
 				break;
 			case PRINT_REVDEP_ALL:
-				expr_print_newline(e, fn, data, E_OR);
-				break;
 			case PRINT_REVDEP_YES:
-				if (expr_calc_value(e) == yes)
-					expr_print_newline(e, fn, data, E_OR);
-				break;
 			case PRINT_REVDEP_MOD:
-				if (expr_calc_value(e) == mod)
-					expr_print_newline(e, fn, data, E_OR);
-				break;
 			case PRINT_REVDEP_NO:
-				if (expr_calc_value(e) == no)
-					expr_print_newline(e, fn, data, E_OR);
-				break;
-			default:
+				expr_print_revdep(e, fn, data, E_OR, type);
 				break;
 			}
 		else
@@ -1283,21 +1300,10 @@  __expr_print(struct expr *e,
 			expr_print(e->right.expr, fn, data, E_AND);
 			break;
 		case PRINT_REVDEP_ALL:
-			expr_print_newline(e, fn, data, E_OR);
-			break;
 		case PRINT_REVDEP_YES:
-			if (expr_calc_value(e) == yes)
-				expr_print_newline(e, fn, data, E_OR);
-			break;
 		case PRINT_REVDEP_MOD:
-			if (expr_calc_value(e) == mod)
-				expr_print_newline(e, fn, data, E_OR);
-			break;
 		case PRINT_REVDEP_NO:
-			if (expr_calc_value(e) == no)
-				expr_print_newline(e, fn, data, E_OR);
-			break;
-		default:
+			expr_print_revdep(e, fn, data, E_OR, type);
 			break;
 		}
 		break;

> 
> >                         default:
> >                                 break;
> >                         }
> > @@ -1273,6 +1285,18 @@ __expr_print(struct expr *e,
> >                 case PRINT_REVDEP_ALL:
> >                         expr_print_newline(e, fn, data, E_OR);
> >                         break;
> > +               case PRINT_REVDEP_YES:
> > +                       if (expr_calc_value(e) == yes)
> > +                               expr_print_newline(e, fn, data, E_OR);
> > +                       break;
> > +               case PRINT_REVDEP_MOD:
> > +                       if (expr_calc_value(e) == mod)
> > +                               expr_print_newline(e, fn, data, E_OR);
> > +                       break;
> > +               case PRINT_REVDEP_NO:
> > +                       if (expr_calc_value(e) == no)
> > +                               expr_print_newline(e, fn, data, E_OR);
> > +                       break;
> 
> That would simplify this part as well, since they're equal.
> 
> >                 default:
> >                         break;
> >                 }
> > @@ -1353,10 +1377,43 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
> >         expr_print(e, expr_print_gstr_helper, gs, E_NONE);
> >  }
> >
> > +/*
> > + * Allow front ends to check if a specific reverse dependency expression
> > + * has at least one top level "||" member which evaluates to "val". This,
> > + * will allow front ends to, as example, avoid printing "Selected by [y]:"
> > + * line when there are actually no top level "||" sub-expressions which
> > + * evaluate to =y.
> > + */
> > +bool expr_revdep_contains(struct expr *e, tristate val)
> > +{
> > +       bool ret = false;
> > +
> > +       if (!e)
> > +               return ret;
> > +
> > +       switch (e->type) {
> > +       case E_SYMBOL:
> > +       case E_AND:
> > +               if (expr_calc_value(e) == val)
> > +                       ret = true;
> > +               break;
> > +       case E_OR:
> > +               if (expr_revdep_contains(e->left.expr, val))
> > +                       ret = true;
> > +               else if (expr_revdep_contains(e->right.expr, val))
> > +                       ret = true;
> > +               break;
> > +       default:
> > +               break;
> > +       }
> > +       return ret;
> > +}
> > +
> >  /*
> >   * Transform the top level "||" tokens into newlines and prepend each
> >   * line with a minus. This makes expressions much easier to read.
> > - * Suitable for reverse dependency expressions.
> > + * Suitable for reverse dependency expressions. In addition, allow
> > + * selective printing of tokens/sub-expressions by their tristate value.
> >   */
> >  void expr_gstr_print_revdep(struct expr *e, struct gstr *gs, enum print_type t)
> >  {
> > diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> > index 21cb67c15091..d5b096725ca8 100644
> > --- a/scripts/kconfig/expr.h
> > +++ b/scripts/kconfig/expr.h
> > @@ -37,6 +37,9 @@ enum expr_type {
> >  enum print_type {
> >         PRINT_NORMAL,
> >         PRINT_REVDEP_ALL,
> 
> PRINT_REVDEP_ALL is unused now, right?
> 
> Guess it doesn't hurt that much to have it there, though I'm more of a
> "it won't be needed" person.

Correct. It remains unused if this patchset is applied. I would avoid
removing PRINT_REVDEP_ALL in the same context with adding support for
PRINT_REVDEP_{YES|MOD|NO}. I think this should be done in a standalone
commit for better visibility (to be reverted easily if ever needed).
Here is how it would look like on top of v3 patchset. Please, provide
your preference if the 6 lines may stay or should be gone.

diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index b91cbc1e20c0..2313a157ebaf 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1199,9 +1199,6 @@  expr_print_revdep(struct expr *e,
 	switch (type) {
 	case PRINT_NORMAL:
 		break;
-	case PRINT_REVDEP_ALL:
-		expr_print_newline(e, fn, data, prevtoken);
-		break;
 	case PRINT_REVDEP_YES:
 		if (expr_calc_value(e) == yes)
 			expr_print_newline(e, fn, data, prevtoken);
@@ -1238,7 +1235,6 @@  __expr_print(struct expr *e,
 			case PRINT_NORMAL:
 				fn(data, e->left.sym, e->left.sym->name);
 				break;
-			case PRINT_REVDEP_ALL:
 			case PRINT_REVDEP_YES:
 			case PRINT_REVDEP_MOD:
 			case PRINT_REVDEP_NO:
@@ -1299,7 +1295,6 @@  __expr_print(struct expr *e,
 			fn(data, NULL, " && ");
 			expr_print(e->right.expr, fn, data, E_AND);
 			break;
-		case PRINT_REVDEP_ALL:
 		case PRINT_REVDEP_YES:
 		case PRINT_REVDEP_MOD:
 		case PRINT_REVDEP_NO:
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index d5b096725ca8..e5687b430c17 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -36,7 +36,6 @@  enum expr_type {
 
 enum print_type {
 	PRINT_NORMAL,
-	PRINT_REVDEP_ALL,
 	PRINT_REVDEP_YES,
 	PRINT_REVDEP_MOD,
 	PRINT_REVDEP_NO,