From owner-freebsd-questions@FreeBSD.ORG Fri Aug 27 20:55:23 2004 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 31BBD16A4D0 for ; Fri, 27 Aug 2004 20:55:23 +0000 (GMT) Received: from nic.ach.sch.gr (nic.sch.gr [194.63.238.4]) by mx1.FreeBSD.org (Postfix) with ESMTP id D154943D46 for ; Fri, 27 Aug 2004 20:55:18 +0000 (GMT) (envelope-from keramida@ceid.upatras.gr) Received: (qmail 12826 invoked by uid 207); 27 Aug 2004 20:55:14 -0000 Received: from keramida@ceid.upatras.gr by nic by uid 201 with qmail-scanner-1.21 (sophie: 3.04/2.19/3.81. Clear:RC:1(81.186.70.104):. Processed in 1.744529 secs); 27 Aug 2004 20:55:14 -0000 Received: from dialup104.ach.sch.gr (HELO gothmog.gr) ([81.186.70.104]) (envelope-sender ) by nic.sch.gr (qmail-ldap-1.03) with DES-CBC3-SHA encrypted SMTP for ; 27 Aug 2004 20:55:12 -0000 Received: from gothmog.gr (gothmog [127.0.0.1]) by gothmog.gr (8.13.1/8.13.1) with ESMTP id i7RKre9r000438; Fri, 27 Aug 2004 23:53:40 +0300 (EEST) (envelope-from keramida@ceid.upatras.gr) Received: (from giorgos@localhost) by gothmog.gr (8.13.1/8.13.1/Submit) id i7RKeMGQ087080; Fri, 27 Aug 2004 23:40:22 +0300 (EEST) (envelope-from keramida@ceid.upatras.gr) Date: Fri, 27 Aug 2004 23:40:22 +0300 From: Giorgos Keramidas To: "Crist J. Clark" Message-ID: <20040827204022.GB53034@gothmog.gr> References: <20040827191324.GA59475@blossom.cjclark.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20040827191324.GA59475@blossom.cjclark.org> Phone: +30-2610-312145 Mobile: +30-6944-116520 cc: questions@freebsd.org Subject: Re: m4 Problems X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 Aug 2004 20:55:23 -0000 On 2004-08-27 12:13, "Crist J. Clark" 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