PDA

View Full Version : Exec Script Parsing Bug



Haldrik
12-29-2015, 06:26 PM
Heyo,


Uncovered a bug with exec. It's not parsing <> correctly.


--- Lich: exec2 active.
[bigshot: inside wait_swing while]
--- SyntaxError: exec2:10: end pattern with unmatched parenthesis: /(?:^<style id=""/
exec2:10: syntax error, unexpected '<'
...if line !~ /(?:^<style id=""/><style id="roomDesc"/>|<compon...
... ^
exec2:10: syntax error, unexpected '>'
...e id=""/><style id="roomDesc"/>|<component id='room objs'>|<...
... ^
exec2:10: syntax error, unexpected '|'
..."/>|<component id='room objs'>|<compDef id='room objs'>)/;
... ^
exec2:10: syntax error, unexpected ')'
...bjs'>|<compDef id='room objs'>)/;
... ^
exec2:17: syntax error, unexpected keyword_end, expecting end-of-input
end;
^
E:/Gemstone IV/lich/lich.rbw:3144:in `eval'
--- Lich: exec2 has exited.

I tried about 10 different ways of the below. Removed (?:), escaped all the <>, split the if statement. Nothing worked.


start_exec_script( <<-eos
status_tags;
while line = get;
echo line if $bigshot_debug;
echo "Inside stop_wait exec" if $bigshot_debug;
echo $global_target if $bigshot_debug;
echo $pcs if $bigshot_debug;
echo $stop_wait if $bigshot_debug;
echo "#{$global_target}.*#{$pcs}" if $bigshot_debug;
if line =~ /#{target.id}.*(#{pcs})/ && line !~ /(?^<style id=""\/><style id="roomDesc"\/>|<component id='room objs'>|<compDef id='room objs'>/ objs'/;
echo "inside if statement for stop_swing exec" if $bigshot_debug;
$stop_wait = true;
end;
break if $stop_wait;
break if !running? 'bigshot';
end;
status_tags;
eos
)


This is the working code:



start_exec_script( <<-eos
status_tags;
while line = get;
echo line if $bigshot_debug;
echo "Inside stop_wait exec" if $bigshot_debug;
echo $global_target if $bigshot_debug;
echo $pcs if $bigshot_debug;
echo $stop_wait if $bigshot_debug;
echo "#{$global_target}.*#{$pcs}" if $bigshot_debug;
if line =~ /#{$global_target}.*#{$pcs}/ and line !~ /style id="".*style id="roomDesc"|(?:component|compDef) id='room objs'/;
echo "inside if statement for stop_swing exec" if $bigshot_debug;
$stop_wait = true;
end;
break if $stop_wait;
break if !running? 'bigshot';
end;
status_tags;
eos
)

Tillmen
12-31-2015, 10:12 AM
The thread title is a little misleading. That's a bug with bigshot, not exec.

The first error message was about unmatched parentheses in a regex. And the first code block shows a regex with an opening parentheses but no closing one.

The next error was an "unexpexted <". The < is unexpected because the regex has accidentally ended, and the code boils down to:

if line =~ regex > nonsense

The reason the regex ended was because the forward slash wasn't escaped well enough. To start this exec script, bigshot is passing a string containing code to the start_exec_script method. So the escaped forward slash is used up when defining this string. You need to escape the backslash so it remains in the string and is a able to escape the forward slash when the string is interpreted as code.

;e echo " /foo\/bar/ "
[exec1: /foo/bar/]

;e echo " /foo\\/bar/ "
[exec1: /foo\/bar/]

Your solution worked because you removed the forward slashes.

BigWorm
12-31-2015, 03:24 PM
Couple other tricks to deal with this.

You could use hard quotes which will avoid the initial backslash escape sequence interpolation:



;e echo ' /foo\/bar/'
[exec2: /foo\/bar/]


You can also use the "percent" syntax for regular expressions to avoid having to escape backslashes. This is especially useful when your regex is something like a file/directory name or xpath:



;e echo "/some/file/path" =~ %r{file}


Note that there are percent notations (http://ruby-doc.org/core-2.1.1/doc/syntax/literals_rdoc.html#label-Percent+Strings) for a lot of other common literal datatypes too. I often use %w[] for arrays of words.

The percent syntax wouldn't have helped here because you are actually passing a string of code to evaluated, not a regular expression. Basically your code is getting evaluated twice which is why you need to double escape everything.

Haldrik
12-31-2015, 09:50 PM
Just real quickly...

Those lines work using ;exec from command line. But not inside an exec script.

Will look in more detail tmw.

EDIT:

Maybe I'm just crazy. I tried it like 20 different ways and thought it was working on ;e from command line. Can't get it to replicate.


Thanks tillmen.