[Top][All Lists]
[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>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- functions `index' and `foreachstar',
Matt Swift <=