m4 Problems

2004-08-27 Thread Crist J. Clark
I want to do something that I _think_ should be rather simple
within m4(1). I want to test if a macro value has been set.
If it is set, I want to modify it and continue. If it is not
set, I want to produce an error message and bail out. However,
it is not working.

Here is an example of a test script,

  $ cat testerr.mc
  ifdef(`TEST', ``TEST' defined.', `TEST not defined.')

  ifdef(`TEST', define(`TEST', `NEW'TEST), errprint(`TEST not specified, exiting.') 
m4exit(1))

  The value of `TEST' is TEST.

Now I run it without TEST set,

  $ m4 testerr.mc
  TEST not defined.

  TEST not specified, exiting. 
  $ echo $?
  1

And it looks good. But now I try with TEST set,

  $ m4 -D TEST=test testerr.mc
  TEST defined.

  TEST not specified, exiting. 
  $ echo $?
  1

And it acts as if it is NOT set. It looks like the third
argument of the second ifdef macro is getting evaluated
even though the first argument is not set.

So, I'll try this test script instead,

  ifdef(`TEST', ``TEST' defined.', `TEST not defined.')

  ifdef(`TEST', define(`TEST', `NEW'TEST), `errprint(`TEST not specified, exiting.') 
m4exit(1)')

  The value of `TEST' is TEST.

And try the set case,

  $ m4 -D TEST=test testerr.mc
  TEST defined.



  The value of TEST is NEWtest.
  $ echo $?
  0

And it works! OK, now check the case where it is not
set,

  $ m4 testerr.mc
  TEST not defined.



  The value of TEST is NEWTEST.
  $ echo $?
  0

So now this case doesn't work.

What quoting scheme do I need to use here to get this to work
correctly? Or is there some other trick to it?  Can someone
explain m4(1)'s order of evaluation and what actually gets
evaluated in each case?
-- 
Crist J. Clark | [EMAIL PROTECTED]
   | [EMAIL PROTECTED]
http://people.freebsd.org/~cjc/| [EMAIL PROTECTED]
___
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: m4 Problems

2004-08-27 Thread Giorgos Keramidas
On 2004-08-27 12:13, Crist J. Clark [EMAIL PROTECTED] wrote:
 I want to do something that I _think_ should be rather simple
 within m4(1). I want to test if a macro value has been set.
 If it is set, I want to modify it and continue. If it is not
 set, I want to produce an error message and bail out. However,
 it is not working.

 Here is an example of a test script,

   $ cat testerr.mc
   ifdef(`TEST', ``TEST' defined.', `TEST not defined.')

   ifdef(`TEST', define(`TEST', `NEW'TEST), errprint(`TEST not specified, exiting.') 
 m4exit(1))

   The value of `TEST' is TEST.

The trick is to avoid evaluation of the two conditional parts by quoting
them at least ONE level more than the enclosing ifdef().  This:

ifdef(`a', foo, bar)

will evaluate both foo anr bar at the same time that ifdef() is
evaluated and checked.  This second form though:

ifdef(`a', `foo', `bar')

will still evaluate `foo' and `bar' at the outter level, yielding foo
and bar, but only one of foo or bar will eventually be evaluated
depending on the value of `a'.

I don't know if this sounds confusing or it helps at all, but here's a
modified version of testerr.mc that works as (I think) you expect:

# cat /tmp/testerr.mc
ifdef(`TEST', ``TEST' defined.', `TEST not defined.')

ifdef(`TEST', `define(`TEST', `NEW'TEST)', `errprint(`TEST not specified, 
exiting.') m4exit(1)')

The value of `TEST' is TEST.

If you don't define TEST, m4exit(1) is evaluated:

# m4 /tmp/testerr.mc
TEST not defined.

TEST not specified, exiting.
 #

Note the SPACE character right before my shell prompt, which is the
space character immediatelly before `m4exit(1)'.

Now, if you *do* define TEST:

# m4 -DTEST=foo /tmp/testerr.mc
TEST defined.



The value of TEST is NEWfoo.
#

The NEW definition is printed ;-)

 What quoting scheme do I need to use here to get this to work
 correctly? Or is there some other trick to it?  Can someone
 explain m4(1)'s order of evaluation and what actually gets
 evaluated in each case?

If you don't quote the arguments to ifdef() they are ALL evaluated and the
result of their evaluation is substituted before the choise of ifdef()
takes place.  This is why regardless of TEST being defined or not the
second part of your ifdef() was evaluated and caused m4exit() to abort the
entire process *before* ifdef() made its choise of what to evaluate next.

To see this in action check the output of the following script:

# cat /tmp/foo.mc
ifdef(`foo', define(`foo', `more'foo), errprint(`foo is 'foo) m4exit(1))

# echo ?
1
# m4 /tmp/foo.mc
foo is morefoo

# m4 -Dfoo=bar /tmp/foo.mc
foo is morebar

# echo $?
1

In both cases keep in mind that the arguments of ifdef() are evaluated once
before ifdef() makes a choise.

a) When foo is undefined, this is evaluated:

define(`foo', `more'foo)

   and `foo' is defined to be `morefoo' (because `foo' is undefined and is
   interpreted literally in the second part of the define().

   Then the second part of ifdef() is evaluated and m4exit() terminates all
   evaluation with an error of 1 after having printed errprint's message.

b) When foo is defined to `bar', exactly the same happens only this time at
   the second argument of define() foo has a different value.

   ...

An entirely different thing happens when you quote the arguments of ifdef():

# cat /tmp/foo2.mc
ifdef(`foo', `define(`foo', `more'foo)', `errprint(`foo is 'foo) m4exit(1)')
foo

# m4 /tmp/foo2.mc
foo is foo

 # echo $?
1

$ m4 -Dfoo=bar /tmp/foo2.mc

morebar

# echo $?
0

I hope all this random m4-rambling helps a bit,

Giorgos

___
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to [EMAIL PROTECTED]