bitwise operators in lua to create string - lua

New user to LUA creating a protocol dissector for Wireshark.
referring to Lua - Bitwise Logical Operations,
I need a function in Lua to create a string based on a converted hex value:
local function HexToCircuitID(val)
-- input: 0x9D81
-- output: "630.1.01"
local e = ((val >> 4) & 0x3) + 1
local f = val & 0xF
local g = val >> 6
return string.format("%d.%d.%02d",e,f,g)
end
the interpreter has a problem with "unexpected symbol near '>' " for the first line with the right-shift operator.
Also, I'm not sure the string format function will operate the same as in C (new to Lua). This function is to create a ProtoField that appears as:
CircuitId: 630.1.01
where the actual value of the field is 0x9D81.

You can use bit.rshift(x, n) to right shift and bit.band(x1[,x2...]) to &.
The function then becomes:
local function HexToCircuitID(val)
-- input: 0x9D81
-- output: "630.1.01"
local e = bit.band(bit.rshift(val, 4), 0x3) + 1
local f = bit.band(val, 0xF)
local g = bit.rshift(val, 6)
--return string.format("%d.%d.%02d",e,f,g)
return string.format("%d.%d.%02d",g,f,e)
end
To get the order right I had to change e,f,g to g,f,e.
This will work in the latest version of Wireshark, which uses Lua 5.2. As Nifim mentioned, you have to use the bit library rather than bitwise operators, as they were introduced in Lua 5.3.

Related

Evaluating expression in Lua in an Environment

This question has some reference to the question Evaluating expression in Lua in Mathematics Environment
The following code works.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. exp, exp, "t", tbl)()
end
print(mathEval("sin(0)"))
print(mathEval("sin(0)+cos(1)+2^2"))
However, the following code does not work.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. tostring(exp), tostring(exp), "t", tbl)()
end
print(mathEval(sin(0)))
print(mathEval(sin(0)+cos(1)+2^2))
I want to evaluate expressions without using quotes. How can that be done?
The problem with the line print(mathEval(sin(0)+cos(1)+2^2)) is that the argument of mathEval is evaluated before mathEval runs, so evaluating the variables sin and cos can not be deferred to the environment of mathEval; that is, mathEval gets a value, and no expression to evaluate at all!
First of all, one option to evaluate such mathematical expressions without the use of mathEval would be to simply temporarily change your environment:
local prev_env = _ENV -- this is needed to restore the environment later on
_ENV = tbl -- enter custom environment
local result = sin(0)+cos(1)+2^2
_ENV = prev_env -- restore environment
print(result)
if you want mathEval as a convenience helper, you'll have to pass the expression as a function returning the value to the expression such that calling the function will evaluate the expression; this allows you to defer the initialization. You'll have to use a powerful function called setfenv which allows you to change the environment of func; this was unfortunately removed in favor of _ENV in Lua 5.2 and later. The code then becomes trivial:
local function mathEval(func)
setfenv(func, tbl)
return func
end
mathEval(function() return sin(0)+cos(1)+2^2 end)
setfenv can be replicated in Lua 5.2 using the debug library, since Lua internally implements _ENV as an upvalue, as shown by Leafo:
local function setfenv(fn, env)
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
I assume you do not want to evaluate the expression before passing the result as an argument? Then you could wrap your expression into a function, which is then lazily called. It replaces the environment with tbl, executes the function, and reverts the environment.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(func)
local old = _ENV
_ENV = tbl
local r = func()
_ENV = old
return r
end
print(mathEval(function() return sin(0)+cos(1)+2^2 end))
You are passing sin(0) and sin(0)+cos(1)+2^2 to the mathEval(exp) function, but since sin and cos are not global variables and the math library is not being passed as an environment, Lua is unable to find them.
If you want to use math functions with the mathEval function, you can use the tbl table created before, to call the math functions, for example:
print(mathEval("tbl.sin(0)"))
print(mathEval("tbl.sin(0)+tbl.cos(1)+2^2"))
or alternatively you can pass the math library or the math functions as an upvalue to the load() function:
function mathEval(exp)
return load("return " .. tostring(exp), tostring(exp), "t", _ENV)()
end
print(mathEval("math.sin(0)"))
print(mathEval("math.sin(0)+math.cos(1)+2^2"))
It is possible to do this without quotes, this should work:
expression = string.format("%s(%d)", "math.sin", 0)
fn = load( "return " .. expression)
result = fn()
print(result) -- Output: 0
In this example, the string.format() function is used to create the string "math.sin(0)". The resulting string is then passed to the load() function as before.
In this way you don't need to use quotes on the string, and you can use placeholders to concatenate the variables.

Do the const and close keywords in Lua actually do anything?

I was excited to learn that, as of Lua 5.4, Lua supports constant (const) and to-be-closed (close) variables! However, upon testing these keywords, they don't seem to do anything at all. I wrote the following code to sample the features to get a better grasp of their exact usage:
function f()
local const x = 3
print(x)
x = 2
print(x)
end
f()
function g()
local close x = {}
setmetatable(x, {__close = function() print("closed!") end})
end
g()
I titled the file constCheck.lua and ran it with lua constCheck.lua. The output is as follows:
3
2
I was expecting an error on my call to f(), or at least for it to print 3 twice, instead it seemed to reassign x with no issue at all. Further, I was expecting the call to g() to print out "closed!" when x left scope at the end of the function, but this did not happen. I can't find very many examples of these keywords' usage. Am I using them properly? Do they work?
Note: lua -v => Lua 5.4.0 Copyright (C) 1994-2020 Lua.org, PUC-Rio
This is <const> not const, and <close> not close
See https://lwn.net/Articles/826134/
do
local x <const> = 42
x = x+1
end
-- ERROR: attempt to assign to const variable 'x'
And some example https://github.com/lua/lua/blob/master/testes/code.lua#L11
local k0aux <const> = 0
https://github.com/lua/lua/blob/master/testes/files.lua#L128
local f <close> = assert(io.open(file, "w"))
From the Lua 5.4 Reference Manual : 3.3.7 - Local Declarations
Each variable name may be postfixed by an attribute ( a name between angle brackets):
attrib ::= [‘<’ Name ‘>’]
There are two possible attributes: const, which declares a constant
variable, that is, a variable that cannot be assigned to after its
initialization; and close, which declares a to-be-closed variable
So you would have to write local x <const> = 3 for example.
Your code local const x = 3 is equivalent to
local const = nil
x = 3
So you're actually creating a local nil value const and a global number value x.

How Can I Convert this Lua Code to be Able to be Used in Older Version? (What is the Order of Precedence of Lua Bitwise Operators?)

I have this Lua code in Lua 5.3 for Base64:
local bs = { [0] =
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
}
local function base64(s)
local byte, rep = string.byte, string.rep
local pad = 2 - ((#s-1) % 3)
s = (s..rep('\0', pad)):gsub("...", function(cs)
local a, b, c = byte(cs, 1, 3)
return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63]
end)
return s:sub(1, #s-pad) .. rep('=', pad)
end
I wanted to use it in older versions, but the problem is it does have the bitwise operators (not library). I can easily replace the symbols to the corresponding functions, but I don't know the precedence of Lua bitwise operators.

Functions in lua tables

I have
someTabe = {}
someTabe.foo = function (x,y)
return x + y
end
How can I get pint(function"(function (x,y) return x + y end)??? Not return result.
You cannot recover the source code of a function from inside Lua.
> print(someTabe.foo)
function: 0x7fed0bc091f0
This is telling you that someTabe.foo contains a function, which has been converted to internal representation stored at the address shown.
If you need to recover the source code of a function from inside Lua, you need to compile it manually with load and then use the debug library to get the source code.
You could could look for a decompiler online if you are just trying to see the code. However in your own code it is impossible.
You can't get code itself, but you can get bytecode using string.dump():
local f = function(x,y) print('AAA') end)
local bytecode = string.dump(f) -- Get bytecode of function
local f2 = load(f) -- It is copy of f, but (f ~= f2)
f2() -- prints AAA

How do I use the bitwise operator XOR in Lua?

How can I implement bitwise operators in Lua language?
Specifically, I need a XOR operator/method.
In Lua 5.2, you can use functions in bit32 library.
In Lua 5.3, bit32 library is obsoleted because there are now native bitwise operators.
print(3 & 5) -- bitwise and
print(3 | 5) -- bitwise or
print(3 ~ 5) -- bitwise xor
print(7 >> 1) -- bitwise right shift
print(7 << 1) -- bitwise left shift
print(~7) -- bitwise not
Output:
1
7
6
3
14
-8
In Lua 5.2, you can use the bit32.bxor function.
Since you're referencing the floor function 3 times, using an excessive number of loops for most operations (numbers less than 2^31 don't need all 31 loops), are using the ^ operator, and aren't capitalizing on the fact that a and b might be wildly different numbers with different magnitudes, you're losing a lot of efficiency. The function also isn't localized, and you're doing two more division operations than you need to. I wrote this to be reasonably fast.
In general, you're going to see improvements of about 3 to 20 times.
local function BitXOR(a,b)--Bitwise xor
local p,c=1,0
while a>0 and b>0 do
local ra,rb=a%2,b%2
if ra~=rb then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
if a<b then a=b end
while a>0 do
local ra=a%2
if ra>0 then c=c+p end
a,p=(a-ra)/2,p*2
end
return c
end
If you need more than this, say AND, OR, and NOT, then I've got you covered there, too.
local function BitOR(a,b)--Bitwise or
local p,c=1,0
while a+b>0 do
local ra,rb=a%2,b%2
if ra+rb>0 then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
return c
end
local function BitNOT(n)
local p,c=1,0
while n>0 do
local r=n%2
if r<1 then c=c+p end
n,p=(n-r)/2,p*2
end
return c
end
local function BitAND(a,b)--Bitwise and
local p,c=1,0
while a>0 and b>0 do
local ra,rb=a%2,b%2
if ra+rb>1 then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
return c
end
Don't worry, you won't need to change anything.
If you're needing an efficient way to do bitwise shifts, I wrote an article about that a while ago. Here's some functions which wrap the technique:
function lshift(x, by)
return x * 2 ^ by
end
function rshift(x, by)
return math.floor(x / 2 ^ by)
end
Try:
function xor(a,b)
return (a or b) and not (a and b)
end
From the OP; moved from question into this answer.
This is how I implemented XOR in Lua:
local floor = math.floor
function bxor (a,b)
local r = 0
for i = 0, 31 do
local x = a / 2 + b / 2
if x ~= floor (x) then
r = r + 2^i
end
a = floor (a / 2)
b = floor (b / 2)
end
return r
end
This is very simple. use NAND logic.
https://en.wikipedia.org/wiki/NAND_logic
function xor(a,b)
return not( not( a and not( a and b ) ) and not( b and not( a and b ) ) )
end
if you also need 1,0 inputs insert the following to the function
a = a==1 or a == true -- to accept nil, 1, 0, true or false
b = b==1 or b == true -- to accept nil, 1, 0, true or false
Hope this helps someone.

Resources