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),\t@echo $(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> _______________________________________________ Bug-make mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-make