bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug #64185] *** only one 'else' per conditional. Stop. due to else in r


From: Harry Clauson
Subject: [bug #64185] *** only one 'else' per conditional. Stop. due to else in recipe
Date: Mon, 22 May 2023 11:47:54 -0400 (EDT)

Follow-up Comment #7, bug #64185 (project make):

I often remind developers that “the tail does not wag the dog”, in the
same way that the current behavior of the code does not define correctness.

While you keep explaining what the parser is currently doing, what I am
reporting is that this is not the correct behavior as described by the GNU
Make documentation.  While the documented behavior makes perfect sense, the
parser behavior you are describing contradicts the documentation as well as
common sense.

Specifically, the documentation clearly defines two fundamental behaviors for
Make Conditionals as follows:

“Extra spaces are allowed and ignored at the beginning of the conditional
directive line, but a tab is not allowed.  (If the line begins with a tab, it
will be considered part of a recipe for a rule.)”

“The other two directives that play a part in a conditional are else and
endif.  Each of these directives is written as one word, with no arguments. 
Extra spaces are allowed and ignored at the beginning of the line, and spaces
or tabs at the end.”

“Conditionals affect which lines of the makefile make uses.  If the
condition is true, make reads the lines of the test-if-true as part of the
makefile; if the condition is false, make ignores those lines completely.”

The two behaviors are:

1. Any lines of code within an inactive conditional branch are entirely
ignored.
2. Conditional directives cannot be confused with recipe lines because they
cannot begin with a tab character. The documentation should be updated to
refer to the .RECIPEPREFIX character, which did not exist prior to Make 3.82.

Lets apply the above statements, in detail, to the behavior you have explained
regarding the excerpt:

all:
ifdef blah
junk:
        else
else
endif

> Here, the parser sees rule 'all:' and begins its search for recipe lines of
'all:'. Then the parser sees 'ifdef blah'. 'blah' is not defined and the
parser
ignores the following line, which is 'junk:'. 

> Then parser reads '\telse' and takes
it as a recipe of 'all:'. 

This is incorrect behavior, because the condition was false so it is in an
inactive branch:

"if the conditon is false, make ignores those lines completely.”

> Because the parser took one of the two elses as a recipe,
there is no complain about extra elses in a conditional.

This is incorrect behavior because the recipe else begins with a tab so it is
not a conditional directive:

“(If the line begins with a tab, it will be considered part of a recipe for
a rule.)”

Since the conditional is false, all lines of code are ignored until the next
conditional (else) preceded only by optional spaces:

"Extra spaces are allowed and ignored at the beginning of the line, and spaces
or tabs at the end.”

The else begins the active branch of the conditional, so any lines of code (in
this case none) until the following conditional endif are passed to the Make
parser.  The endif ends the active branch and the scope of the conditional.

The correct result is that only the following lines of code are "seen" by the
Make parser:

all:

Similarly, for the second excerpt:

all:

$(info hello)
ifdef blah
junk:
    else
else
endif

> Here, $(info hello) ends the search for recipe lines of 'all'.
By the time the parser reads 'ifdef blah' it is no longer looking for recipe
lines.

> The parser then ignores 'junk:', because 'blah' is not defined and
treats '\telse' as a conditional directive.

This is incorrect behavior because conditional directives cannot begin with a
tab character:

“(If the line begins with a tab, it will be considered part of a recipe for
a rule.)”

As above, since the conditional was false, all lines of code will be ignored
until it reaches the next conditional directive:

"if the conditon is false, make ignores those lines completely.”

As above, the conditional directive else terminates the inactive branch and
begins the active branch until the conditional directive endif terminates the
active branch and the scope of the conditional.

The correct result is that the following lines of code are "seen" by the Make
parser:

all:

$(info hello)

It may be helpful to understand that Make conditionals are defined to behave
similarly to "C" pre-processor conditionals, in that each line of code is
first examined and handled as follows:

1. If the line is a conditional directive, it is processed as such and the
"state" of any conditional is adjusted accordingly (none, active conditional
branch, inactive conditional branch).
2. Otherwise, if the "state" is currently an inactive conditional branch, the
line is ignored.
3. Otherwise, the line of code is passed to the code parser.



    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?64185>

_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]