bug-make
[Top][All Lists]
Advanced

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

functions `index' and `foreachstar'


From: Matt Swift
Subject: functions `index' and `foreachstar'
Date: Sun, 15 Dec 2002 13:56:56 -0500
User-agent: Gnus/5.090008 (Oort Gnus v0.08) Emacs/21.2 (i386-debian-linux-gnu)

I just put a patch onto Savannah with two new experimental functions
`index' and `foreachstar' (dumbly named!), and I am writing this mail
to explain it a bit.

Well, I started to explain, and I ended up rambling and theorizing --
and not just a little, and now I want to go make sure Miami loses to
Oakland, so I'm going to give a brief explanation :)

    `$(index FIND,IN)'
         Searches IN for an occurrence of FIND.  If it occurs, the value of the 
function is
         the index of IN in FIND, starting with 1; otherwise, the value is 0.

         Compare the function `findstring'.

         You can use this function in a conditional to test for the presence of 
a
         specific substring in a given string.  Thus, the two examples,

              $(index a,a b c)
              $(index a,b c)

         produce the values `1' and `0', respectively.

         When $(index $(a), $(x)) is not `0', 
         $(word $(index $(a), $(x)), $(x)) is always equal to $(a).


   `$(foreachstar ...)'
       Like foreach, but separate components with newline instead of space, for 
use with $(eval ..).
       I really need to think of a better name for this function!




I wrote the new functions before seeing the thread last month about
the bug in the `eval' function and the debate about it.  I think I
have been after the same sort of goal.  I've just now installed the
post-3.80 patches on my system, and soon will experiment to see what
might work now that didn't work before.

When I read about the new features in 3.80 and began to experiment,
one of the tasks I set for myself was to write a target that caused
the name and value of every variable to be echoed in a simple way.

It proved too hard for me!  Can anyone do this?  It's typical, I
think, of what one wants `eval' to help do.

I wrote the two functions `index' and `foreachstar' to try to take
`eval' that last few yards to being the feature of our dreams.

Basically, the `index' function, working with `word' or `wordlist',
can help implement the kind of record-structure that seems to me is
the main stumbling block, insofar as before `eval' it could only be
done if the data themselves had a structure such that %-patterns would
inherently provide your array/record structure.  For example:

    targets          = public        private         professional
    target.machines  = webserver.com localhost       toolndie.com
    target.porno-p   = no            yes             no
    target.dirs      = web           web/me          web/me/work


    # argument TARGET, expands to the stamp associated with it
    stamp-of      = $(word $(index $(1), $(targets)), $(target.stamps))
    target.stamps = $(foreach t, $(target), $(call stamp-of, $(t)))

(I haven't worked out this example carefully enough to assure that it
can't be done another way, but if it can, I've almost definitely
proved that I did need `index' in situations that are about like this.)


Below is a test Makefile and its output.  The error at the end comes
up when Make tries to print out a variable value that has a newline in
it -- the evaluator doesn't read past the newline.  That's a problem
to resolve.

(Incidentally, I run with "env -i" because something weird is going on
with Make having variables defined after my shell functions -- I've
submitted a bug report to Debian, but it may affect you if you try
this at home.)



--------begin Makefile


# testing new functions $(index ...) and $(foreach* ...)

nums = one two three four five

all: index foreach dumpvars

index:
        @echo "triplets are:"
        @echo '  $$(index ...)'
        @echo '  expected result of $$(index ...)'
        @echo '  $$(findstring ...) for comparison'
        @echo
        @echo 'blorkle! I don'"'"'t like how $$(findstring ...) works!'
        @echo
        @echo --
        @echo "[$(index one, $(nums))]"
        @echo "[1]"
        @echo "[$(findstring one, $(nums))]"
        @echo --
        @echo "[$(index bobo, $(nums))]"
        @echo "[0]"
        @echo "[$(findstring bobo, $(nums))]"
        @echo --
        @echo "[$(index five, $(nums))]"
        @echo "[5]"
        @echo "[$(findstring five, $(nums))]"
        @echo --
        @echo "[$(index on, $(nums))]"
        @echo "[0]"
        @echo "[$(findstring on, $(nums))]"
        @echo --
        @echo "[$(index fo, $(nums))]"
        @echo "[0]"
        @echo "[$(findstring fo, $(nums))]"
        @echo --
        @echo "[$(index hree, $(nums))]"
        @echo "[0]"
        @echo "[$(findstring hree, $(nums))]"
        @echo --
        @echo "[$(index ne tw, $(nums))]"
        @echo "[0]"
        @echo "[$(findstring ne tw, $(nums))]"
        @echo --

define doit
        @echo $(1)
endef

# eval has to deal with a whole rule etc or it barfs

# can't have comments beggining at boln in this def: "missing separator"
# this line ditto:
#       $(foreachstar x, $(nums),address@hidden $(x))

define fofo
foreach:
        @echo "should see \"$(nums)\" one per line"
        @echo
        @echo "using call and \`foreach' -- doesn't work"
        $(foreach x, $(nums),$(call doit, $(x)))
        @echo
        @echo "using call and \`foreachstar' -- works"
        $(foreachstar x, $(nums),$(call doit, $(x)))
        @echo
        @echo "using explicit tab and \`foreachstar' -- works"
        $(foreachstar x, $(nums),       @echo $(x))
        @echo
        @echo "done"
endef
$(eval $(fofo))

define WHOOPS
this variable has 
                  a newline in it and Make will barf on it
endef

define gendumpvars
dumpvars:
        @echo "Look at my nice variables!"
        @echo "I will tell you all of the following secrets, plus WHOOPS:"
        @echo "$(filter-out fofo gendumpvars WHOOPS, $(.VARIABLES))"
        @echo ---------------------------------------
        $(foreachstar v,$(filter-out fofo gendumpvars, $(.VARIABLES)),  @echo 
'$(v): $(value $(v))')
        @echo "All done now!"
endef
$(eval $(gendumpvars))


.PHONY: all index foreach dumpvars gendumpvars

#       echo $(eval $(foreach* x, $(nums), $(call doit, $(x))))
#       $(eval $(foreach x, $(nums),$(call doit, $(x))))




----------- end Makefile, being its output


    [beth] makehack> env -i /usr/local/bin/make-debug
    triplets are:
      $(index ...)
      expected result of $(index ...)
      $(findstring ...) for comparison

    blorkle! I don't like how $(findstring ...) works!

    --
    [1]
    [1]
    [one]
    --
    [0]
    [0]
    []
    --
    [5]
    [5]
    [five]
    --
    [0]
    [0]
    [on]
    --
    [0]
    [0]
    [fo]
    --
    [0]
    [0]
    [hree]
    --
    [0]
    [0]
    [ne tw]
    --
    should see "one two three four five" one per line

    using call and `foreach' -- doesn't work
    one @echo two @echo three @echo four @echo five

    using call and `foreachstar' -- works
    one
    two
    three
    four
    five

    using explicit tab and `foreachstar' -- works
    one
    two
    three
    four
    five

    done
    Look at my nice variables!
    I will tell you all of the following secrets, plus WHOOPS:
    <D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO PREPROCESS.F LINK.o OUTPUT_OPTION 
COMPILE.cpp MAKEFILE_LIST LINK.p CC CHECKOUT,v CPP LINK.cc LD TEXI2DVI YACC 
COMPILE.mod ARFLAGS LINK.r LINT COMPILE.f LINT.c YACC.y AR TANGLE GET %F 
COMPILE.F nums CTANGLE .LIBPATTERNS LINK.C LINK.S PREPROCESS.r LINK.c LINK.s ^D 
MAKE AS PREPROCESS.S COMPILE.p MAKE_VERSION FC %D WEAVE MAKE_COMMAND LINK.cpp 
F77 COMPILE.cc .VARIABLES PC *F COMPILE.def LEX MAKEFLAGS MFLAGS *D doit LEX.l 
+D COMPILE.r +F M2C MAKEFILES <F CXX COFLAGS COMPILE.C ^F COMPILE.S LINK.F 
SUFFIXES COMPILE.c COMPILE.s MAKELEVEL MAKEINFO TEX F77FLAGS LINK.f
    ---------------------------------------
    <D: 
    ?F: 
    CWEAVE: cweave
    ?D: 
    @D: .
    @F: dumpvars
    CURDIR: /var/tmp/devel/makehack
    SHELL: /bin/sh
    RM: rm -f
    CO: co
    PREPROCESS.F: f77    -F
    LINK.o: cc  
    OUTPUT_OPTION: -o dumpvars
    COMPILE.cpp: g++    -c
    MAKEFILE_LIST:  Makefile
    LINK.p: pc    
    CC: cc
    CHECKOUT,v: +co   dumpvars
    CPP: cc -E
    LINK.cc: g++    
    LD: ld
    TEXI2DVI: texi2dvi
    YACC: yacc
    COMPILE.mod: m2c   
    ARFLAGS: rv
    LINK.r: f77    
    LINT: lint
    COMPILE.f: f77   -c
    LINT.c: lint   
    YACC.y: yacc 
    AR: ar
    TANGLE: tangle
    GET: get
    %F: 
    COMPILE.F: f77    -c
    nums: one two three four five
    CTANGLE: ctangle
    .LIBPATTERNS: lib%.so lib%.a
    LINK.C: g++    
    LINK.S: cc    
    PREPROCESS.r: f77    -F
    LINK.c: cc    
    LINK.s: cc   
    /bin/sh: -c: line 1: unexpected EOF while looking for matching `''
    /bin/sh: -c: line 2: syntax error: unexpected end of file
    make-debug: *** [dumpvars] Error 2
    [beth] makehack> 



reply via email to

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