ulfalizer/Kconfiglib

Macro expansion evaluation

leandrolanzieri opened this issue · 4 comments

I'm observing a weird behaviour on macro evaluation. In my use case there might or not be a constant symbol defined. Based on that some decisions should be taken (e.g. show/hide a menuconfig or assign a default to a symbol). Here is an illustrative Kconfig example:

Kconfig example
mainmenu "This is the main menu"

module-is-defined-somewhere = y
module = "$(module-is-defined-somewhere)" != ""

config DEFAULT_TEN
    int "Default to 10"
    default 10 if "$(module-is-defined-somewhere)" != ""
    default 1

config DEFAULT_ONE
    int "Default to 1"
    default 10 if $(module)
    default 1

Case 1: If module-is-defined-somewhere is defined, then DEFAULT_TEN defaults to the value 10, and DEFAULT_ONE to 1. Inspecting the symbols defaults on menuconfig shows:

DEFAULT_TEN

        default 10 if y != ""
        default 1

DEFAULT_ONE

        default 10 if "y" != ""(undefined/n)
        default 1

Case 2: If module-is-defined-somewhere is commented out from the Kconfig file, then both symbols default to 1, showing in menuconfig:

DEFAULT_TEN

        default 10 if "" != ""
        default 1

DEFAULT_ONE

        default 10 if "" != ""(undefined/n)
        default 1

I even tried defining module = $(module-is-defined-somewhere) != "" but results are similar.

I'm not sure if I'm misinterpreting the way these macros should work. Is there a way to check in the Kconfig if a constant symbol is defined or not?

Hello,

What I think is going is that $(module) expands to "y" != "", which you expected to be reparsed afterwards. No reparsing is done on expanded macro values though, so what you end up with is a reference to a symbol that's literally called "y" != "" (the (undefined/n) refers to that weirdly-named symbol).

Another way to put it is that $(foo) always expands to (part of) a single token.

This is compatible with how the preprocessor works in the C tools. It's mentioned in the caveats section of kconfig-macro-language.rst as well.

I was thinking of maybe adding a warning when a macro expands to something with whitespace in it (and maybe other stuff that shouldn't appear in symbol names) and isn't expanded within quotes. I agree that it's pretty cryptic right now.

That limitation was semi-deliberate when it was put into the C tools, IIRC, though I think it started out as a side effect of wanting to be able to do "foo $(bar) baz" without any issues if the expansion of $(bar) happens to have a quote in it.

Unrelated, but the reason you get y instead of "y" in the first case is that y is a shorthand for "y". __str__() uses that shorthand as well.

@ulfalizer thanks for your quick response!

Another way to put it is that $(foo) always expands to (part of) a single token.

Totally right. Now that you put it this way the behaviour makes sense, I was expecting the macro to expand across tokens, which is not allowed.

I was thinking of maybe adding a warning when a macro expands to something with whitespace in it (and maybe other stuff that shouldn't appear in symbol names) and isn't expanded within quotes. I agree that it's pretty cryptic right now.

Could be useful some hint on those cases.