Paul, I can see your points. I may not agree with them ;-), but I understand them.
In the case where someone wants to put 'endef', or any of the others as the first word of a command, one could always remove the specialness of the keyword by escaping, or quoting, it. Example: <tab>define macro <tab>tgt: <tab><tab>\endef ... <tab>endef or <tab>define macro <tab>tgt: <tab><tab>'endef' ... <tab>endef This would work for any of GNUmake's keywords. All would be handled the same way. IMO, this is a much better solution that standing on our heads to support the rare case where 'endef', et. al, might be used as the first word of a command. And, I tried to define a target within a define/endef -- it doesn't work. Example: define macro all:: <tab>@echo command1 <tab>@echo command2 endef $(macro) Results in: make: *** No rule to make target ' ', needed by all. Stop. I would think it should work, but it doesn't. Effectively removing one of your arguments. So, IMO, all these reserved words (ifndef, ..., endif, define, endef) should always be recognized - regardless of leading blanks/tabs, and if you want to use one of these reserved words as the first word of a command, then you need to escape, or quote it. Consistency is a good thing. Consistency across make versions is even better. Reid Madsen -----Original Message----- From: Paul Smith [mailto:[EMAIL PROTECTED] On Behalf Of Paul D. Smith Sent: Tuesday, August 02, 2005 11:25 AM To: Madsen, Reid; Reid Madsen Cc: bug-make@gnu.org Subject: Re: [bug #13877] Error parsing define/endef when both are indented using tabs Hi Reid; I'm posting this to bug-make for a wider audience. %% Reid Madsen <[EMAIL PROTECTED]> writes: rm> Now regarding #2 -- the '<tab>endef' issue. GNUmake supports rm> conditional structures implemented with 'ifdef', 'ifndef', 'ifeq', rm> 'ifneq', 'else', 'endif'. In addition it supports macro definition rm> using 'define' and 'endef'. All of these are considered to be rm> reserved words in GNUmake. With the notable exeception of 'endef' rm> all of the above can be indented using tabs. I've attached a rm> Makefile to #13877 that illustrates this. It looks like: rm> <tab>ifdef FOO rm> <tab>endif rm> <tab>ifndef BAR rm> <tab>endif rm> <tab>ifeq ($(FOO),) rm> <tab>endif rm> <tab>ifneq ($(BAR),) rm> <tab>endif rm> <tab>define macro rm> <tab><tab>@echo macro text rm> endef rm> all: ; $(macro) Your makefile is not constructed properly to see the problem. Try this: instead of putting the "all" target at the bottom of the file, move it to the top of the file (or even put it into the middle). NOW you see the issue. Try removing the syntax error by either indenting the endef with a TAB or removing that line... now you'll see without question that all those supposed "make keywords" are not being treated specially by make at all: they're considered to be shell script commands. This was true in GNU make 3.76 as well, AFAIK. rm> All you can see, everything but 'endef' can be indented with rm> tabs. That's not quite true. As you'll see with the experiment above, EVERY SINGLE (logical) LINE in a makefile follows the same rule: if it begins with a TAB, and it's in a context where it COULD be part of a command script, then it IS considered part of a command script--regardless of the contents. That goes for ALL the special keywords, like ifdef, endif, etc. etc. This is true even for comment lines! Remember that blank lines and (non-TAB indented) comment lines (and even conditionals) do NOT end a command script: only another target line or a variable definition can end a command script. rm> Thus, the requirement that the 'endef' must appear at start rm> of line makes absolutely no sense. It also makes no sense that rm> the 'define' is allowed to be indented using a tab, but that the rm> matching 'endef' cannot be indented similarly with a tab. "define" (etc.) is NOT allowed to be indented by a TAB _if_ it comes in the context of a command script. You'll get other kinds of errors if you, for example, use <TAB>ifdef in a command script context, then use spaces to indent the endif... in that case the ifdef will not be seen by make (it will be considered part of the command script) and you'll get an error saying that you have an extraneous endif. Play around with changing various TABs to spaces in your example above, with the "all" target first, and see what I mean. rm> Once, you've entered the 'do_define()' function, the only purpose rm> is to find the matching 'endef'. You are known to be in a rm> 'define' statement and the 'define' statement could not be a part rm> of a rule. Unfortunately endef presents a special problem. You're correct that the define statement itself cannot be part of a rule, but the define statement can unquestionably CONTAIN a rule, like this: define DO_TARGET target: @echo $@ endef Now, if the endef is indented by a TAB, the meaning is ambiguous: does it mean that the next line in the command script for the "target" should be the command "endef", or does it mean that the define statement is being ended? EVERYWHERE else in GNU make, as I said above, if a line could be considered part of a command script it IS considered part of a command script, even if it looks a whole lot like a make conditional etc. Further complicating matters, GNU make does not parse the contents of the define to determine whether or not the endef actually DOES appear in a command context. So, make is simply assuming that any character indented with a TAB inside the define is meant to be part of a command script. rm> The documentation states: "The 'define' directive is followed on rm> the same line by the name of the variable and nothing more. rm> ... The end of the value is marked by a line containing just rm> containing the work 'endef'." It is unclear from the rm> documentation whether the 'define' or 'endef' may be indented, but rm> since 'define' may be indented, it follows that 'endef' could be rm> indented as well. As I've said above, the 'define' cannot be indented either, _IF_ it appears on a command script context. I've not made a decision on this yet, and I'm still thinking about ways we might be able to make this work without breaking make's general rule. I will say that in my opinion in this case adherence to the general rule (TAB introduces a command script line) is more important than backward-compatibility to version 3.76. However, I want to point out that in make it is a *very* bad idea to EVER use a TAB as the first character on any line that is not intended to be a command script. Doing so causes your makefile to be brittle and easy to break in confusing and often difficult to find ways. For example, if someone were to add a target in the middle of any of the ifdef/define/export/variable setting/whatever statements in your makefile, all of a sudden those lines become part of that target's command script instead of being recognized by make. I realize you have a very large existing system but if I were you I would consider it a good idea, for the sake of reliability and robustness, to bite the bullet and make the change from TAB to 8 spaces (or whatever). -- ------------------------------------------------------------------------ ------- Paul D. Smith <[EMAIL PROTECTED]> Find some GNU make tips at: http://www.gnu.org http://make.paulandlesley.org "Please remain calm...I may be mad, but I am a professional." --Mad Scientist _______________________________________________ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make