I'm trying pass the fully evaluated value of a recursive make variables to a $(shell ...). I've tried many ways, including a macro to compute the final value myself, but have not had success.
I'm getting the intermediate variable syntax in my shell instead of the fully expanded recursive variable value.
VAR1 ?= var1_value
VAR2 ?= var2_value1 var2_value2
VAR3 ?= $(VAR1)
VARLIST := VAR1 VAR2 VAR3
quote = $(if $(call ne,$(words $(1)),1),"$(1)",$(1))
GENVARS1 = $(foreach v,$(1),set $(v) $(call quote,$(value $(v)));)
SHELLVARLIST = $(shell echo $(call GENVARS1,$(VARLIST)))
shelltest :
#echo "--->Executing recipe for shelltest"
#echo "VAR3 is $(VAR3)"
$(call GENVARS,$(VARLIST))
#echo "SHELLVARLIST = $(SHELLVARLIST)"
In an ordinary dereference (at least in a recipe), the variable is fully expanded. However, when passed to macro as an argument, it does not. Is there any way to get the fully expanded value into a macro argument?
Here's the result when running make:
bash-4.1$ make -f test_expand.mk shelltest
/bin/sh: VAR1: command not found
--->Executing recipe for shelltest
VAR3 is var1_value
set VAR1 var1_value; set VAR2 var2_value1 var2_value2; set VAR3 $(VAR1);
/bin/sh: VAR1: command not found
SHELLVARLIST = set VAR1 var1_value
As you can see, $(VAR3) does not get passed as "var1_value" but instead gets passed as the literal "$(VAR1)".
Any hints or pointers would be most welcome. This is hair-pullingly frustrating (and I have so little left... :-o)
Thanks,
Dave
You are explicitly telling make to NOT expand the variable, by using the $(value $(V)) construct. That's what the value function does: avoids expansion.
If you want expansion, get rid of the value function. Why did you add it there in the first place?
GENVARS1 = $(foreach v,$(1),set $(v) $(call quote,$(v));)
ETA
Sorry, if you want the expansion of the value as a variable name, you need to add an extra level of $(...) to expand it:
GENVARS1 = $(foreach v,$(1),set $(v) $(call quote,$($(v)));)
The inner $(v) expands to the name of the variable such as VAR3, so then the outer $(...) will be $(VAR3) and expand to the value of the VAR3 variable.
Related
I want to save the output of a program to a variable.
I use the following approach ,but fail.
$ PIPE RUN TEST | DEFINE/JOB VALUE #SYS$PIPE
$ x = f$logical("VALUE")
I got an error:%DCL-W-MAXPARM, too many parameters - reenter command with fewer parameters
\WORLD\
reference :
How to assign the output of a program to a variable in a DCL com script on VMS?
The usual way to do this is to write the output to a file and read from the file and put that into a DCL symbol (or logical). Although not obvious, you can do this with the PIPE command was well:
$ pipe r 2words
hello world
$ pipe r 2words |(read sys$pipe line ; line=""""+line+"""" ; def/job value &line )
$ sh log value
"VALUE" = "hello world" (LNM$JOB_85AB4440)
$
IF you are able to change the program, add some code to it to write the required values into symbols or logicals (see LIB$ routines)
If you can modify the program, using LIB$SET_SYMBOL in the program defines a DCL symbol (what you are calling a variable) for DCL. That's the cleanest way to do this. If it really needs to be a logical, then there are system calls that define logicals.
I would like to create a csh alias that performs one operation if invoked without arguments and a second operation if invoked with a single argument. Does anyone know how to do this? (Attempting to refer to an argument that wasn't passed triggers an error).
I know this is a bit late but I just ran into needing something similar and hope it might still be relevant to somebody.
You can set the arguments as an array and query based on the size of the array:
alias testing 'set args_=(\!*); if ($#args_ > 0) echo "this command has $#args_ arguments" endif'
Aliases in tcsh are limited; for more advanced things, I've found that the best way is to source a (t)csh script, like so:
alias my-cmd 'source ~/.tcsh/my-cmd.tcsh'
And ~/.tcsh/my-cmd.tcsh would contain something like:
if ( $1 != '' ) then
echo "we have an argument: $1"
else
echo "we don't have an argument"
endif
Example output:
% my-cmd
we don't have an argument
% my-cmd hello
we have an argument: hello
Now, it may also be possible to do this with just an alias, but this will be much more maintainable & cleaner in the long run, IMHO.
(I've assumed tcsh here since almost all, or perhaps even all, c shells are tcsh these days).
Easy to do - sorry I'm late to the party.
alias iftest 'if (\\!:0 != \\!:$) echo "Last arg="\\!:$;if (\\!:0 == \\!:$) echo "No args given."'
This merely checks whether the 0th argument (=the 'iftest' itself) and the last arguments are the same, and if they are, assumes there is no argument. This is, of course, not necessarily true, but hopefully works in praxis.
I have to write a tcsh script for unix that pulls values from every other line in a text file, compares them and decides if you should buy(1), sell(-1) or do nothing(0). Basically a simple stock profit calculation. I think I have all the logic right, but when I run the script I get a "while syntax error" and it never executes. I have the full script below, is it not possible to nest statements in a while loop with unix? If so any suggestions how to do this?
#!/bin/tcsh
set lineNum='wc -l testcase.txt'
set i=1
while ($i<$lineNum)
set prices='sed -n '$lineNump' testcase.txt'
set arr=( $price )
set j='echo ${#arr}'
set price=0
set x=0
set y=0
set k=0
while ($k < $j)
set a=arr[$k]
set str=""
if ($a>$price)
then
str="$str 1"
price=$((price-a))
else if($a<$price)
then
str="$str -1"
price=$((price+a))
else if($a==$price)
then
str="$str 0"
fi
str="$str $price"
if ($str=='sed -n'('expr $lineNum+1'p)' testcase.txt')
then
x=$((x+1))
fi
y=$((y+1))
end
lineNum=$((lineNum+2))
end
echo $x/$y
Your script appears to be a mixture of tcsh and bash syntax.
As Mark's answer says, the then keyword has to be on the same line as the if (unless you use a backslash to splice two lines, but there's not much point in doing that).
For a variable assignment, the set keyword is not optional; this:
str="$str 1"
is a syntax error in csh/tcsh (it will probably look for a command whose name starts with "str=".) Write that as:
set str = "$str 1"
Note that you can optionally have spaces around the = in a set. tcsh's syntax is a bit messed up:
set foo=bar # ok
set foo = bar # ok
set foo= bar # ok
set foo =bar # error: "Variable name must begin with a letter."
The x=$((x+1)) syntax is specific to bash and related shells. tcsh uses # for arithmetic assignments:
set x = 42
# x ++ # sets $x to 43
# x = $x * 2 # sets $x to 86
If you have a choice, I suggest writing your script to use bash rather than tcsh (you're about halfway there already). Its syntax is much more regular.
The classic rant about csh/tcsh programming can be found here.
You are missing the end statement correspoding to the first while.
You are also using fi instead of endif.
The "then" keywords need to be on the same line as the "if" they belong to.
In my Windows batch file I have a various amount of variables. Lets say I have the following variables:
set varTest1=test1
set varTest2=test2
set otherVar=variable500
set varS=string
set yetAnotherVar=foo
They do really make no sense buts thats not the point. I am looking for a method that prints out all values of variables that start with var:
So when I run my batch with a certain help parameter it should print out all three variables starting with var and its value.
The output could look like this:
These are the available variables:
varTest1 : test1
varTest2 : test2
varS : string
I created the following for reading the parameter:
IF "%1" == "" (
echo No help parameter was set. Program will exit. ) ELSE (
IF "%1" == "help" (
call :showAllAvailableVars ) ELSE (
echo Do something else))
Now I would have my method
:showAllAvailableVars
I think the solution could be something with the findstr method but I could not figure it out how to do that because findstr is mainly for files and not for searching through own program variables.
Create array instead of different variables. Like,
set var[0]=test1
set var[1]=test2
set var[2]=string
then in your 'showAllAvailableVars' function do this
for /L %%i in (1,1,%n%) do echo !var[%%i]!
You could use set var to print all variables which begins with var.
See also set /?
I have a makefile with the following code. I'm trying to set a variable in an if statement. It doesn't error, but %OPTION% just prints %OPTION (with only one percentage sign) and the $(OPTION) doesn't print anything. Please help
Makefile
RELEASE_OR_DEBUG=debug
init:
SET OPTION=test
#echo test1 = %OPTION%
#echo test2 = $(OPTION)
if ".$(RELEASE_OR_DEBUG)" == ".debug" SET OPTION="-d"
#echo OPTION = %OPTION%
#echo OPTION = $(OPTION)
Output
test1 = %OPTION
test2 =
if ".debug" == ".debug" SET OPTION="-d"
OPTION = %OPTION
OPTION = $(OPTION)
You cannot set variables inside dependency statements (such as "init" in this case). In fact, you can't use if statements there either. Variables can be set by external batch files prior to calling the makefile (and that batch file then can call the makefile) or outside of dependency statements like RELEASE_OR_DEBUG in this example.
To access variables inside dependency statements, use $(VARIABLE_NAME). Be aware that if the variable name is not found, it will simply use a blank string (such as in your "#echo test2 = $(OPTION)" test where the variable OPTION was not found).