I have the text of function call like this below:
Send(0x39,((rLoss>>8)&0xFF),(rLoss&0xFF) );
I want to convert this text so the function passes by pointer. I have written two macros like:
BYTE0(var) ((uint8_t *)&var)
BYTE1(var) ((uint8_t)&var)+1)
I want the result to be:
Send(0x39,BYTE1(rLoss),BYTE0(rLoss) );
Can you please help me do this in Perl?
I presume that the first argument to the call is always a hex number that doesn't have to be examined or transformed. I've also presumed that args 2 and 3 are always ANDed with 0xFF. Finally, I've presumed that the function being called and the argument being shifted are simple words - i.e. match \w+
. With these presumptions, the following appears to do what you want;
use v5.12;
while (<>) {
chomp ;
if (/ ^ (\w+) \( .* \) \s* ; $ /x) {
my $call = $1 ; # function name being called
s/ ^ \w+ \( //x ; # Strip off fn call and open paren
s/ \) \s* ; \s* $ //x ; # Strip off close paren and semicolon
my ($arg1 , $arg2 , $arg3) = split ',' ; # split into arguments of the call
my $new_args = join("," , $arg1 , transform($arg2) , transform($arg3)) ;
say "$call($new_args );" ;
}
else {
say $_ ;
}
}
sub transform {
$_ = shift ;
my $replacement ;
s/ ^ \s* \( //x; # Strip off opening paren
s/ \) \s* $ //x; # Strip off closing paren
s/ & 0xFF $ //x ; # Strip off ANDing all ones
if (/^ \w+ $/x) { # Simple var name left?
$replacement = "BYTE0(" . $_ . ")" ;
}
elsif (/ ^ \( (\w+) >> (\d+) \) $ /x) { # var name shifted some number of bits
my $var_name = $1 ;
my $shift_size = $2 ;
my $byte_num = $shift_size / 8 ;
$replacement = "BYTE" . $byte_num . "(" . $var_name . ")" ;
}
else {
warn "Don't understand '$_' on line $.\n";
$replacement = $_ ;
}
return $replacement
}
It's unix filter style - input on STDIN, transformed output on STDOUT. When I feed it this made up data;
hello
Send(0x39,((rLoss>>8)&0xFF),(rLoss&0xFF) );
world
Receive(0x12,(rWin&0xFF),((rWin>>16)&0xFF) );
bye
It spits out
hello
Send(0x39,BYTE1(rLoss),BYTE0(rLoss) );
world
Receive(0x12,BYTE0(rWin),BYTE2(rWin) );
bye
Hopefully, the inline comments explain the code. The decision on whether to attempt to transform the line or leave it alone is based solely on the first regex - a word (fn call) followed by something in parentheses - this may or may not be what you want. Perhaps you know that its always a call to "Send" in which case you can put that in the regex.
The only other thing you may not be familiar with is the integer division operator '/'. This is used to translate the number of bits being shifted to the BYTE num macro call.