Makefile macro modifier - linux

I am totally confused about the following macro modifier in a Makefile I have come onto,
TOOLS = $(TOOL_ROOTS:%=$(OBJDIR)%$(TOOL_SUFFIX))
Here
TOOL_ROOTS=some filename prefixes
OBJDIR=$HOME/obj/
TOOL_SUFFIX=.so
Can someone tell me what this line actually means?

TOOL_ROOTS must be getting assigned some value other than the empty string at some point or that does nothing (which I'll show in a moment).
So first things first just expanding the variables takes us from:
TOOLS = $(TOOL_ROOTS:%=$(OBJDIR)%$(TOOL_SUFFIX))
to:
TOOLS = $(:%=~/obj%.so)
(which we can immediately see doesn't look right, and as I'll explain in a moment doesn't do anything)
So lets pretend it has a value instead.
TOOL_ROOTS = shovel axe hammer
And try the expansion again:
TOOLS = $(shovel axe hammer:%=~/obj%.so)
(That OBJDIR definition looks odd also. I would expect it to be ~/obj/ or something... and that's ignoring that ~ is a bad choice here and that $HOME would be much better.)
The next thing we need to know is what that syntax is all about. Well it is a Substitution Reference.
A substitution reference substitutes the value of a variable with alterations that you specify. It has the form ‘$(var:a=b)’ (or ‘${var:a=b}’) and its meaning is to take the value of the variable var, replace every a at the end of a word with b in that value, and substitute the resulting string.
When we say “at the end of a word”, we mean that a must appear either followed by whitespace or at the end of the value in order to be replaced; other occurrences of a in the value are unaltered. For example:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
sets ‘bar’ to ‘a.c b.c c.c’. See Setting Variables.
A substitution reference is actually an abbreviation for use of the patsubst expansion function (see Functions for String Substitution and Analysis). We provide substitution references as well as patsubst for compatibility with other implementations of make.
Another type of substitution reference lets you use the full power of the patsubst function. It has the same form ‘$(var:a=b)’ described above, except that now a must contain a single ‘%’ character. This case is equivalent to ‘$(patsubst a,b,$(var))’. See Functions for String Substitution and Analysis, for a description of the patsubst function.
For example:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
sets ‘bar’ to ‘a.c b.c c.c’.
So, the first % there is matching the entirety of every word in the value of the variable (here shovel axe hammer) and then replacing each value with the expansion of the second part.
So shovel becomes ~/objshovel.so, etc. and we end up with:
TOOLS = ~/objshovel.so ~/objaxe.so ~/objhammer.so
See what I meant about OBJDIR being odd before? OBJDIR=~/obj/ would have left us with this instead:
TOOLS = ~/obj/shovel.so ~/obj/axe.so ~/obj/hammer.so
which makes a lot more sense to me.

Related

Extracting variables from expression in Lua

I have expressions in lua which contains standard metatable operations .__add,.__sub,.__mul, (+,-,*)
For example a+b*xyz-cdeI am trying to extract all free variables in table. For this expression, the table will contain {a,b,xyz,cde}. Right now I am trying it with string operations, like splitting, substituting etc. This seems to work but I feel it as ugly way. It gets little complicated as there may nesting and brackets involved in expressions. For example, the expression (a+b)-c*xyz*(a+(b+c)) should return table {a,b,c,xyz}. Can there be a simple way to extract free variables in expressions? I am even looking for simple way with string library.
If you want to do string processing, it's easy:
local V={}
local s="((a+b)-c*xyz*(a+(b+c)))"
for k in s:gmatch("%a+") do
V[k]=k
end
for k in pairs(V) do print(k) end
For fun, you can let Lua do the hard work:
local V={}
do
local _ENV=setmetatable({},{__index=function (t,k) V[k]=k return 0 end})
local _=((a+b)-c*xyz*(a+(b+c)))
end
for k in pairs(V) do print(k) end
This code evaluates the expression in an empty environment where every variable has the value zero, saving the names of the variables in the expression in a table.

Finding substring of variable length in bash

I have a string, such as time=1234, and I want to extract just the number after the = sign. However, this number could be in the range of 0 and 100000 (eg. - time=1, time=23, time=99999, etc.).
I've tried things like $(string:5:8}, but this will only work for examples of a certain length.
How do I get the substring of everything after the = sign? I would prefer to do it without outside commands like cut or awk, because I will be running this script on devices that may or may not have that functionality. I know there are examples out there using outside functions, but I am trying to find a solution without the use of such.
s=time=1234
time_int=${s##*=}
echo "The content after the = in $s is $time_int"
This is a parameter expansion matching everything matching *= from the front of the variable -- thus, everything up to and including the last =.
If intending this to be non-greedy (that is, to remove only content up to the first = rather than the last =), use ${s#*=} -- a single # rather than two.
References:
The bash-hackers page on parameter expansion
BashFAQ #100 ("How do I do string manipulations in bash?")
BashFAQ #73 ("How can I use parameter expansion? How can I get substrings? [...])
BashSheet quick-reference, paramater expansion section
if time= part is constant you can remove prefix by using ${str#time=}
Let's say you have str='time=123123' if you execute echo ${str#time=} you would get 123123

Make substitution reference on strong containing equals sign

I'm trying to use a Make substitution reference to alter a string. The problem being that the string happens to contain an equals = symbol.
For example:
INPUT = -switch1 -switch2=potato -switch3
OUTPUT = $(INPUT:-switch2=%=-switch2=turnip)
all:
#echo TEST : $(OUTPUT)
so in the form $(var:a=b), INPUT is var, -switch2=% is a and -switch2=turnip is b.
Obviously that doesn't work because = is a special character in this context, but I've no idea how to make it realize that this is part of string a.
I've tried quoting, backslashes, alternative escape characters and putting -switch2=% in a variable and using that instead. All to no avail.
I know I can use patsubst, but that'd be adding the first non-POSIX extension to the file and i'd prefer to not be that guy.
Any suggestions appreciated!
You'll have to use a full patsubst function. Substitution references are just a shortcut for patsubst:
OUTPUT = $(patsubst -switch2=%,-switch2=turnip,$(INPUT))

What's the point of nesting brackets in Lua?

I'm currently teaching myself Lua for iOS game development, since I've heard lots of very good things about it. I'm really impressed by the level of documentation there is for the language, which makes learning it that much easier.
My problem is that I've found a Lua concept that nobody seems to have a "beginner's" explanation for: nested brackets for quotes. For example, I was taught that long strings with escaped single and double quotes like the following:
string_1 = "This is an \"escaped\" word and \"here\'s\" another."
could also be written without the overall surrounding quotes. Instead one would simply replace them with double brackets, like the following:
string_2 = [[This is an "escaped" word and "here's" another.]]
Those both make complete sense to me. But I can also write the string_2 line with "nested brackets," which include equal signs between both sets of the double brackets, as follows:
string_3 = [===[This is an "escaped" word and "here's" another.]===]
My question is simple. What is the point of the syntax used in string_3? It gives the same result as string_1 and string_2 when given as an an input for print(), so I don't understand why nested brackets even exist. Can somebody please help a noob (me) gain some perspective?
It would be used if your string contains a substring that is equal to the delimiter. For example, the following would be invalid:
string_2 = [[This is an "escaped" word, the characters ]].]]
Therefore, in order for it to work as expected, you would need to use a different string delimiter, like in the following:
string_3 = [===[This is an "escaped" word, the characters ]].]===]
I think it's safe to say that not a lot of string literals contain the substring ]], in which case there may never be a reason to use the above syntax.
It helps to, well, nest them:
print [==[malucart[[bbbb]]]bbbb]==]
Will print:
malucart[[bbbb]]]bbbb
But if that's not useful enough, you can use them to put whole programs in a string:
loadstring([===[print "o m g"]===])()
Will print:
o m g
I personally use them for my static/dynamic library implementation. In the case you don't know if the program has a closing bracket with the same amount of =s, you should determine it with something like this:
local c = 0
while contains(prog, "]" .. string.rep("=", c) .. "]") do
c = c + 1
end
-- do stuff

Simple string replacement set of rules

I have an application where users set up a bunch of objects by filling up a bunch of text boxes which represent values that these objects will take. Just like setting up a Person object which requires you to enter a Name and a LastName properties.
Now I want to introduce global variables that the user will be able to assign values to, or which's values will change during the execution of the program. And I want the user to be able to use them when filling up any object's properties. My first idea was to choose an special character that will mark the beginning of a variable name, and then let the user use the character itself twice to represent the character itself.
For instance, say I have a global variable called McThing. Then, say the symbol I choose to mark the beginning of a variable is %. The user would then be able to enter as a person's last name the string "Mc. %McThing", which then I'd replace using the value of McThing. If McThing's value is "Donalds", the last name would become "Mc. Donalds".
The problem with this is that, if I'd have a variable called He and another called Hello and the user enters "%Hello" as the string I wouldn't know which variable needs to be replaced. I could change my rules to, for instance, use the "%" symbol to mark both the beginning and the end of the variable name. But I'm not sure whether this will cause any other problem.
What would be the simplest possible set of rules to achieve this such that the user will be able to represent every possible string without ambiguities? Ideally, the variable names can have any character but I could restrict their names to a given set of characters.
Your approach of marking both beginning and end with % has one problem. What happens if the input string is %foo%%bar%? Do I get the value of foo and the value of bar? Or do I get the value of foo%bar? (Of course if % in variable names isn't allowed, this isn't a problem.)
The simplest way I can think of to avoid this problem is to use one symbol for the beginning and another (e.g. #) for the end. That should avoid any ambiguity. If the user wants a # in text or a variable name, he escapes it like so: %#. This causes no problems, since empty variable names are not a thing (at least I hope not).
It will be fine and easy to implement on the assumptions that:
You have no empty variable names (i.e. if we see a %% is that a % or an empty variable name?)
Variable names cannot contain %s (i.e. if we see a % in a variable name, is that the end or a %?)
OR
Variable names cannot start or end with % and you cannot have 2 variable names in a row
(i.e. is %a%%b% = a and b or a%b?)
These assumptions will ensure that any %% always represents a % character, and any % always represents the start or the end of the string.
These assumptions might not necessarily be required, but at the very least they will make the implementation a lot more difficult (with the above assumptions, we never have to look more than 1 character forward).
An alternative with no such restrictions, loosely based on the way C/Java/etc. does it:
Have % take on a role similar to \ in C/Java/etc. - use:
%s to denote the start of the string
%e to denote the end of the string
%% to denote the % character
You can also use the same characters to represent the start and end, but, we may as well make them different so it's easier to read.

Resources