You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1289 lines
41 KiB
1289 lines
41 KiB
@rem = '
|
|
@goto endofperl
|
|
';
|
|
|
|
use Time::Local;
|
|
use frsobjsup;
|
|
|
|
|
|
package main;
|
|
|
|
|
|
my (%CMD_VARS, %CMD_PARS);
|
|
my $DEBUG = 0; # set to one (or use -verbose=all to see emitted comments
|
|
my $DEBUG_EXPAND = 0;
|
|
my $DEBUG_CHECK = 0; # emit check code to dump FRS_SUB args.
|
|
my $DEBUG_PARSE = 0;
|
|
my $DEBUG_CODE = 0;
|
|
|
|
|
|
my $InFile;
|
|
my $infilelist;
|
|
my $inlinenumber;
|
|
|
|
my $FrsObjectNames = 'FRS_MEMBER|FRS_CONNECTION|FRS_REPLICASET|FRS_SCHEDULE|FRS_SERVER|FRS_SETTINGS';
|
|
my $FrsFunctionNames = 'FRS_SET|FRS_COUNT_SET|FRS_ARRAY|FRS_STAGGER|FRS_STAGGER_BY|FRS_SHOW';
|
|
|
|
my %FRS_CALLS = (
|
|
FRS_MEMBER => {
|
|
CALL => 1, NSETS => 1,
|
|
INTRO => 'FRS_MEMBER->New(', CLOSE => ');',
|
|
ARGS => ['UNDER', 'COMPUTER', 'ONAME', 'MAKE_PRIMARY_MEMBER'],
|
|
},
|
|
|
|
FRS_CONNECTION => {
|
|
CALL => 1, NSETS => 0,
|
|
INTRO => 'FRS_CONNECTION->New(', CLOSE => ');',
|
|
ARGS => ['UNDER', 'FROM', 'ONAME', 'SCHED', 'OPTIONS', 'FLAGS', 'ENABLED'],
|
|
},
|
|
|
|
FRS_REPLICASET => {
|
|
CALL => 1, NSETS => 1,
|
|
INTRO => 'FRS_REPLICASET->New(', CLOSE => ');',
|
|
ARGS => ['UNDER', 'SCHED', 'ONAME', 'FLAGS', 'TYPE', 'FILE_FILTER', 'DIR_FILTER'],
|
|
},
|
|
|
|
FRS_SCHEDULE => {
|
|
CALL => 1, NSETS => 1,
|
|
INTRO => 'FRS_SCHEDULE->New(', CLOSE => ');',
|
|
ARGS => ['REPL_INTERVAL', 'REPL_DURATION', 'TIME_ZONE', 'REPL_OFFSET', 'METHOD',
|
|
'STAGGER', 'OVERRIDE', 'DISABLE', 'TYPE', 'NAME'],
|
|
},
|
|
|
|
FRS_SERVER => {
|
|
CALL => 1, NSETS => 9,
|
|
INTRO => 'FRS_SERVER->New(', CLOSE => ');',
|
|
ARGS => ['RP', 'SP', 'COMPUTER', 'NAME', 'WORKPATH', 'MAKE_PRIMARY_MEMBER'],
|
|
},
|
|
|
|
FRS_SETTINGS => {
|
|
CALL => 1, NSETS => 1,
|
|
INTRO => 'FRS_SETTINGS->New(', CLOSE => ');',
|
|
ARGS => ['DN', 'ONAME'],
|
|
},
|
|
|
|
FRS_COUNT_SET => {
|
|
CALL => 2, NSETS => 0, #inline func
|
|
INTRO => 'scalar @{ ', CLOSE => '}',
|
|
ARGS => ['SET'],
|
|
},
|
|
|
|
FRS_ARRAY => {
|
|
CALL => 2, NSETS => 0, #inline func
|
|
INTRO => '@{ ', CLOSE => '}',
|
|
ARGS => ['SET'],
|
|
},
|
|
|
|
FRS_STAGGER => {
|
|
CALL => 1, NSETS => 0,
|
|
INTRO => 'FRS_SCHEDULE::FRS_STAGGER(', CLOSE => ');',
|
|
ARGS => ['SCHED'],
|
|
},
|
|
|
|
FRS_STAGGER_BY => {
|
|
CALL => 1, NSETS => 0,
|
|
INTRO => 'FRS_SCHEDULE::FRS_STAGGER_BY(', CLOSE => ');',
|
|
ARGS => ['SCHED', 'ADJUST'],
|
|
},
|
|
|
|
FRS_SET => {
|
|
CALL => 0, NSETS => 0,
|
|
INTRO => '@{ FRSSUP::FRS_SET(', CLOSE => ') }',
|
|
ARGS => ['SET'],
|
|
},
|
|
|
|
FRS_SHOW => {
|
|
CALL => 0, NSETS => 0,
|
|
INTRO => 'FRSSUP::FRS_SHOW(', CLOSE => ');',
|
|
ARGS => ['SET'],
|
|
},
|
|
);
|
|
|
|
|
|
my %FRS_ARGS = (
|
|
ADJUST => { TYPE => 'VALUE_INT' },
|
|
COMPUTER => { TYPE => 'VALUE_STR' },
|
|
DIR_FILTER => { TYPE => 'VALUE_STR' },
|
|
DISABLE => { TYPE => 'VALUE_TIME_LIST' },
|
|
DN => { TYPE => 'VALUE_STR' },
|
|
ENABLED => { TYPE => 'VALUE_INT' },
|
|
FILE_FILTER => { TYPE => 'VALUE_STR' },
|
|
FLAGS => { TYPE => 'VALUE_INT' },
|
|
FROM => { TYPE => 'SET_ELEMENT' },
|
|
METHOD => { TYPE => 'VALUE_CHOICE_SINGLE',
|
|
CHOICES => ['REPEAT', 'CUSTOM'] },
|
|
NAME => { TYPE => 'VALUE_STR' },
|
|
ONAME => { TYPE => 'VALUE_STR' },
|
|
OPTIONS => { TYPE => 'VALUE_CHOICE_LIST', CHOICES => [] },
|
|
OVERRIDE => { TYPE => 'VALUE_TIME_LIST' },
|
|
REPL_DURATION => { TYPE => 'VALUE_TIME_SINGLE' },
|
|
REPL_INTERVAL => { TYPE => 'VALUE_TIME_SINGLE' },
|
|
REPL_OFFSET => { TYPE => 'VALUE_TIME_SINGLE' },
|
|
RP => { TYPE => 'VALUE_STR' },
|
|
WORKPATH => { TYPE => 'VALUE_STR' },
|
|
SCHED => { TYPE => 'SCHEDULE' },
|
|
SET => { TYPE => 'SET_REF_SET' },
|
|
SP => { TYPE => 'VALUE_STR' },
|
|
SERVER => { TYPE => 'SET_ELEMENT' },
|
|
STAGGER => { TYPE => 'VALUE_TIME_SINGLE' },
|
|
TIME_ZONE => { TYPE => 'VALUE_SIGN_TIME' },
|
|
TYPE => { TYPE => 'VALUE_CHOICE_SINGLE',
|
|
CHOICES => ['', 'SYSVOL', 'DFS', 'OTHER'] },
|
|
UNDER => { TYPE => 'SET_ELEMENT' },
|
|
TO => { TYPE => 'SET_ELEMENT' },
|
|
PRIMARY_MEMBER => { TYPE => 'SET_ELEMENT' },
|
|
MAKE_PRIMARY_MEMBER => { TYPE => 'VALUE_BOOL' },
|
|
);
|
|
|
|
my %FRS_ARG_TYPES = (
|
|
SET_REF_SINGLE => { INTRO => '&FRSSUP::SelectSet("', CLOSE => '")->[0]' },
|
|
#SET_REF_SET => { INTRO => '&FRSSUP::SelectSet("', CLOSE => '")' },
|
|
SET_REF_SET => { INTRO => '', CLOSE => '' },
|
|
#SET_ELEMENT => { INTRO => '&FRSSUP::SelectSet("', CLOSE => '")->' },
|
|
SET_ELEMENT => { INTRO => '', CLOSE => '' },
|
|
#SCHEDULE => { INTRO => '&FRSSUP::SelectSet("', CLOSE => '")->' },
|
|
SCHEDULE => { INTRO => '', CLOSE => '' },
|
|
ARG_REF => { INTRO => 'XXX', CLOSE => 'TBD' },
|
|
VALUE_INT => { INTRO => 'XXX', CLOSE => '' },
|
|
VALUE_CHOICE_SINGLE => { INTRO => 'XXX', CLOSE => '' },
|
|
VALUE_CHOICE_LIST => { INTRO => 'XXX', CLOSE => '' },
|
|
VALUE_STR => { INTRO => '', CLOSE => '' },
|
|
VALUE_BOOL => { INTRO => '', CLOSE => '' },
|
|
VALUE_SIGN_TIME => { INTRO => '', CLOSE => '' },
|
|
VALUE_TIME_SINGLE => { INTRO => '', CLOSE => '' },
|
|
VALUE_TIME_LIST => { INTRO => '', CLOSE => '' },
|
|
VARCON => { INTRO => '', CLOSE => '' },
|
|
|
|
);
|
|
|
|
|
|
#
|
|
#
|
|
my @SubDefCleanup;
|
|
$SubDefActive = 0;
|
|
$SubList = '';
|
|
|
|
sub Trim {
|
|
my @str = @_;
|
|
for (@str) {s/^\s+//; s/\s+$//;}
|
|
|
|
return wantarray ? @str : $str[0];
|
|
}
|
|
|
|
|
|
sub ParseArgList {
|
|
my $record = shift;
|
|
my @result = ();
|
|
|
|
#
|
|
# return an array of parsed parameters of the form lhs=rhs seperated by "/"
|
|
# backslash can be used as an escape character and quoted strings are skipped
|
|
# (i.e. they are not matched for a "/" separator)
|
|
#
|
|
# The examples below show the input string (with leading "/" removed)
|
|
# followed by a string with ":" separating each returned result.
|
|
#
|
|
# RP=foo /R\P="D:\RSB" /SP="D:\staging" /COMPUTER="bchb/hubsite/servers/" /NAME="bchb.hubsite.ajax.com" /XXX
|
|
# RP=foo :R\P="D:\RSB" :SP="D:\staging" :COMPUTER="bchb/hubsite/servers/" :NAME="bchb.hubsite.ajax.com" :XXX
|
|
#
|
|
# COMPUTER = "bchb/hubsite/servers/" /NAME="bchb.hubsite.ajax.com" /XXX
|
|
# COMPUTER = "bchb/hubsite/servers/" :NAME="bchb.hubsite.ajax.com" :XXX
|
|
#
|
|
# YYY /"$ff.CO\MPUTER" = "bchb/hub"xx"site/ser""vers/" /NAME="bchb.hubsite.ajax.com" /XXX
|
|
# YYY :"$ff.CO\MPUTER" = "bchb/hub"xx"site/ser""vers/" :NAME="bchb.hubsite.ajax.com" :XXX
|
|
#
|
|
# CO\MPUTER = bchb\/hub"xx"site\/servers\//NAME="bchb.hubsite.ajax.com" /XXX
|
|
# CO\MPUTER = bchb\/hub"xx"site\/servers\/:NAME="bchb.hubsite.ajax.com" :XXX
|
|
#
|
|
# CO\MPUTER = bchb\/hub"xx"site\/servers\/////NAME="bchb.hubsite.ajax.com /XXX
|
|
# CO\MPUTER = bchb\/hub"xx"site\/servers\/::::NAME="bchb.hubsite.ajax.com /XXX
|
|
#
|
|
|
|
|
|
$record =~ s:^(\s*/)*::; # remove leading white space and leading "/"
|
|
$record =~ s:(/\s*)*$::; # remove trailing slashes followed by white space
|
|
|
|
while ( $record =~ m{
|
|
\s* # skip leading whitespace
|
|
( # Start of captured result
|
|
(?:[^\"\\/]* # swallow chars up to " or \ or /
|
|
|
|
(?: # followed by 3 alternatives
|
|
(?=/|$) # 1. positive lookahead assertion for / or eos ends match
|
|
|(?:\\.) # 2. if backslash, swallow it + next char
|
|
|(?:\" # 3. if leading quote then find end of quoted
|
|
# string but respect backslash escape char.
|
|
(?:[^\"\\]* # swallow up to next " or \ if any
|
|
|
|
(?:\\. # if prev ended on \ then swallow it + next char
|
|
[^\"\\]* # continue to next quote or \, if any
|
|
)* # loop if we hit \
|
|
)
|
|
\"? # consume trailing quote, if any. could be eos
|
|
)
|
|
|
|
) # end of 3 alternatives
|
|
)+ # continue after quoted string or \
|
|
) /? # end match with next / (if any) ends captured result
|
|
|
|
| ([^/]+) /? # no quotes up to next /, if any, or eos
|
|
|
|
| / # eat extra slash
|
|
}gx ) {
|
|
print "## pre:'$`' match:'$+' post:'$'' lastparen:'$+' \n" if $DEBUG_PARSE;
|
|
# print " match:'$+' \t\t lastparen:'$+' \n";
|
|
push (@result, Trim($+)) if (Trim($+) ne '');
|
|
}
|
|
|
|
# push (@result, undef) if substr($record,-1,1) eq '/';
|
|
return @result;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub CleanInput {
|
|
my $record = shift;
|
|
|
|
#
|
|
# look for a comment symbol '#' that is not part of a quoted string and not
|
|
# escaped with a backslash.
|
|
# return the string up to the comment.
|
|
#
|
|
if (!($record =~ m/\#/)) {
|
|
return $record;
|
|
}
|
|
|
|
while ( $record =~ m{
|
|
( # Start of captured result
|
|
(?:[^\"\\\=]* # swallow chars up to " or \ or #
|
|
|
|
(?: # followed by 3 alternatives
|
|
(?=\#) # 1. positive lookahead assertion for # ends match
|
|
|(?:\\.) # 2. if backslash, swallow it + next char
|
|
|(?:\" # 3. if leading quote then find end of quoted
|
|
# string but respect backslash escape char.
|
|
(?:[^\"\\]* # swallow up to next " or \ if any
|
|
|
|
(?:\\. # if prev ended on \ then swallow it + next char
|
|
[^\"\\]* # continue to next quote or \, if any
|
|
)* # loop if we hit \
|
|
)
|
|
\"? # consume trailing quote, if any. could be eos
|
|
)
|
|
|
|
) # end of 3 alternatives
|
|
)+ # continue after quoted string or \
|
|
) \#? # end match with next # (if any) ends captured result
|
|
|
|
| ([^\#]+) /? # no quotes up to next #, if any, or eos
|
|
|
|
| \# # eat extra #
|
|
}x ) { # no g since we only want first non-quoted #
|
|
print "## pre:'$`' match:'$+' post:'$'' lastparen:'$+' \n" if $DEBUG_PARSE;
|
|
# print "Switch match:'$+' \t\t lastparen:'$+' \n";
|
|
return $+;
|
|
}
|
|
|
|
return $record;
|
|
}
|
|
|
|
|
|
sub FindBalParens {
|
|
my $record = shift;
|
|
|
|
my ($pre, $match, $result);
|
|
my $count = 0;
|
|
my $post = '';
|
|
my $trailbs = '';
|
|
my $leftparfound = 0;
|
|
#
|
|
# Look for the first expression with balanced parens.
|
|
# Parens that are part of a quoted string or escaped with a backslash are skipped.
|
|
#
|
|
# The return value is a 3 element array:
|
|
# [0] n=-1 means extra right parens found.
|
|
# n=0 means a balanced expr found or no parens at all.
|
|
# n>0 means n extra Left Parens found.
|
|
# [1] contains the consumed part of the input string if [0] <= 0 above.
|
|
# otherwise it contains the entire input string
|
|
# [2] contains the remaining part of the string if [0] <= 0 above
|
|
# otherwise it is the null string except for the no parens found case.
|
|
#
|
|
# In the case of no parens found outside of quoted string or escaped chars
|
|
# [0] is zero, [1] is the input string, [2] = "FRS-NO-PARENS".
|
|
#
|
|
#print $record, "\n";
|
|
|
|
if (!($record =~ m/[\(\)]/)) {
|
|
print "## 0, Found: $record Rest: FRS-NO-PARENS\n" if $DEBUG_PARSE;
|
|
return (0, $record, "FRS-NO-PARENS"); # return 0 if no parens found.
|
|
}
|
|
|
|
if ($record =~ m/\\+$/) {
|
|
($trailbs) = $record =~ m/(\\+$)/; # strip trailing \ so they don't foul marker
|
|
$record =~ s/(\\+$)//;
|
|
}
|
|
|
|
$record .= '(*)'; # append marker
|
|
|
|
while ( $record =~ m{
|
|
( # Start of captured result
|
|
(?:[^\"\\\(\)]* # swallow chars up to " or \ or ( or )
|
|
|
|
(?: # followed by 4 alternatives
|
|
(?=\() # 1. positive lookahead assertion for ( ends match
|
|
|(?=\)) # 2. positive lookahead assertion for ) ends match
|
|
|(?:\\.) # 3. if backslash, swallow it + next char
|
|
|(?:\" # 4. if leading quote then find end of quoted
|
|
# string but respect backslash escape char.
|
|
(?:[^\"\\]* # swallow up to next " or \ if any
|
|
|
|
(?:\\. # if prev ended on \ then swallow it + next char
|
|
[^\"\\]* # continue to next quote or \, if any
|
|
)* # loop if we hit \
|
|
)
|
|
\"? # consume trailing quote, if any. could be eos
|
|
)
|
|
|
|
) # end of 4 alternatives
|
|
)+ # continue after quoted string or \
|
|
[\(\)]? # end match with next ( or ) (if any) ends captured result
|
|
|
|
| (?:[^\(]+) /? # no quotes up to next (, if any, or eos
|
|
|
|
| \( # eat extra (
|
|
|
|
)
|
|
}gx ) {
|
|
|
|
$pre = $`; $match = $+; $post = $';
|
|
#
|
|
# if the marker "(*)" is consumed in the match then we must be
|
|
# in the middle of a quoted string so leave count unchanged.
|
|
# Otherwise the marker would have been split.
|
|
#
|
|
if (substr($+,-3,3) ne '(*)') {
|
|
if (substr($+,-1,1) eq ')') {$count--;}
|
|
if (substr($+,-1,1) eq '(') {$count++;}
|
|
#
|
|
# remember finding a left paren if count > 0 and it wasn't
|
|
# caused by a split marker.
|
|
#
|
|
if (($count > 0) && ($post ne '*)')) {$leftparfound = 1;}
|
|
}
|
|
|
|
print "## ($count) paren match:'$+'\n" if $DEBUG_PARSE;
|
|
|
|
#
|
|
# if the count hits zero then return balanced part.
|
|
# if the count goes negative then we've seen more right parens than left parens
|
|
#
|
|
if ($count <= 0) {goto RETURN;}
|
|
}
|
|
|
|
RETURN:
|
|
#
|
|
# Clean off the marker.
|
|
#
|
|
$result = $pre . $match;
|
|
|
|
if ($post =~ m/\(\*\)$/) {
|
|
substr($post, -3, 3) = '';
|
|
} else {
|
|
if ($post eq '*)') { # check for a split marker.
|
|
$post = '';
|
|
substr($result, -1, 1) = '';
|
|
} else {
|
|
$result =~ s/\(\*\)$//;
|
|
}
|
|
}
|
|
|
|
#
|
|
# add back trailing backslashes
|
|
#
|
|
if ($post ne "") {
|
|
$post .= $trailbs;
|
|
} else {
|
|
$result .= $trailbs;
|
|
#
|
|
# The entire string was consumed so if the Count is zero
|
|
# check if we ever found an unquoted left paren. If not
|
|
# then return "FRS-NO-PARENS" as the result in [2].
|
|
#
|
|
if (($count == 0) && ($leftparfound == 0)) {$post = "FRS-NO-PARENS";}
|
|
}
|
|
|
|
print "## $count, Found: $result Rest: $post \n" if $DEBUG_PARSE;
|
|
return ($count, $result , $post );
|
|
}
|
|
|
|
|
|
sub FindBalBrace {
|
|
my $record = shift;
|
|
|
|
my ($pre, $match, $result);
|
|
my $count = 0;
|
|
my $post = '';
|
|
my $trailbs = '';
|
|
my $leftparfound = 0;
|
|
#
|
|
# Look for the first expression with balanced braces.
|
|
# bracess that are part of a quoted string or escaped with a backslash are skipped.
|
|
#
|
|
# The return value is a 3 element array:
|
|
# [0] n=-1 means extra right brace found.
|
|
# n=0 means a balanced expr found or no braces at all.
|
|
# n>0 means n extra Left bracess found.
|
|
# [1] contains the consumed part of the input string if [0] <= 0 above.
|
|
# otherwise it contains the entire input string
|
|
# [2] contains the remaining part of the string if [0] <= 0 above
|
|
# otherwise it is the null string except for the no parens found case.
|
|
#
|
|
# In the case of no parens found outside of quoted string or escaped chars
|
|
# [0] is zero, [1] is the input string, [2] = "FRS-NO-BRACES".
|
|
#
|
|
#print $record, "\n";
|
|
|
|
if (!($record =~ m/[\{\}]/)) {
|
|
print "## 0, Found: $record Rest: FRS-NO-BRACES\n" if $DEBUG_PARSE;
|
|
return (0, $record, "FRS-NO-BRACES"); # return 0 if no parens found.
|
|
}
|
|
|
|
if ($record =~ m/\\+$/) {
|
|
($trailbs) = $record =~ m/(\\+$)/; # strip trailing \ so they don't foul marker
|
|
$record =~ s/(\\+$)//;
|
|
}
|
|
|
|
$record .= '{*}'; # append marker
|
|
|
|
while ( $record =~ m&
|
|
( # Start of captured result
|
|
(?:[^\"\\\{\}]* # swallow chars up to " or \ or { or }
|
|
|
|
(?: # followed by 4 alternatives
|
|
(?=\{) # 1. positive lookahead assertion for { ends match
|
|
|(?=\}) # 2. positive lookahead assertion for } ends match
|
|
|(?:\\.) # 3. if backslash, swallow it + next char
|
|
|(?:\" # 4. if leading quote then find end of quoted
|
|
# string but respect backslash escape char.
|
|
(?:[^\"\\]* # swallow up to next " or \ if any
|
|
|
|
(?:\\. # if prev ended on \ then swallow it + next char
|
|
[^\"\\]* # continue to next quote or \, if any
|
|
)* # loop if we hit \
|
|
)
|
|
\"? # consume trailing quote, if any. could be eos
|
|
)
|
|
|
|
) # end of 4 alternatives
|
|
)+ # continue after quoted string or \
|
|
[\{\}]? # end match with next { or } (if any) ends captured result
|
|
|
|
| (?:[^\{]+) /? # no quotes up to next {, if any, or eos
|
|
|
|
| \{ # eat extra {
|
|
|
|
)
|
|
&gx ) {
|
|
|
|
$pre = $`; $match = $+; $post = $';
|
|
#
|
|
# if the marker "(*)" is consumed in the match then we must be
|
|
# in the middle of a quoted string so leave count unchanged.
|
|
# Otherwise the marker would have been split.
|
|
#
|
|
if (substr($+,-3,3) ne '{*}') {
|
|
if (substr($+,-1,1) eq '}') {$count--;}
|
|
if (substr($+,-1,1) eq '{') {$count++;}
|
|
#
|
|
# remember finding a left paren if count > 0 and it wasn't
|
|
# caused by a split marker.
|
|
#
|
|
if (($count > 0) && ($post ne '*}')) {$leftparfound = 1;}
|
|
}
|
|
|
|
print "## ($count) paren match:'$+'\n" if $DEBUG_PARSE;
|
|
|
|
#
|
|
# if the count hits zero then return balanced part.
|
|
# if the count goes negative then we've seen more right parens than left parens
|
|
#
|
|
if ($count <= 0) {goto RETURN;}
|
|
}
|
|
|
|
RETURN:
|
|
#
|
|
# Clean off the marker.
|
|
#
|
|
$result = $pre . $match;
|
|
|
|
if ($post =~ m/\{\*\}$/) {
|
|
substr($post, -3, 3) = '';
|
|
} else {
|
|
if ($post eq '*}') { # check for a split marker.
|
|
$post = '';
|
|
substr($result, -1, 1) = '';
|
|
} else {
|
|
$result =~ s/\{\*\}$//;
|
|
}
|
|
}
|
|
|
|
#
|
|
# add back trailing backslashes
|
|
#
|
|
if ($post ne "") {
|
|
$post .= $trailbs;
|
|
} else {
|
|
$result .= $trailbs;
|
|
#
|
|
# The entire string was consumed so if the Count is zero
|
|
# check if we ever found an unquoted left paren. If not
|
|
# then return "FRS-NO-PARENS" as the result in [2].
|
|
#
|
|
if (($count eq 0) && ($leftparfound eq 0)) {$post = "FRS-NO-BRACES";}
|
|
}
|
|
|
|
print "## $count, Found: $result Rest: $post \n" if $DEBUG_PARSE;
|
|
return ($count, $result , $post );
|
|
}
|
|
|
|
|
|
sub ExtractParams {
|
|
my $rest = shift;
|
|
#
|
|
# Starting with the input string find the next paren balanced expression
|
|
# in the input stream, consuming more input as needed.
|
|
# Returns a two element array. [0] balanced paren text, [1] the rest of the
|
|
# last input line read.
|
|
#
|
|
my (@BalParen, $ParamStr);
|
|
|
|
@BalParen = FindBalParens($rest);
|
|
|
|
while (($BalParen[0] gt 0) || ($rest eq "FRS-NO-PARENS")) {
|
|
if (!($_ = <F>)) {
|
|
EmitError($_, "EOF hit looking for ')'");
|
|
exit;
|
|
}
|
|
chop;
|
|
|
|
|
|
if (m/\#/) {$_ = CleanInput($_)}; # remove trailing comment string.
|
|
s/^\s+//; # remove leading & trailing white space
|
|
s/\s+$//;
|
|
next if ($_ eq '');
|
|
&EmitComment ($_);
|
|
|
|
#
|
|
# If we are in a DEFSUB then scan for calling params replacement strings.
|
|
# If found then insert a ref to __args hash.
|
|
#
|
|
if ($SubDefActive) {
|
|
if ( s/\%(\w+)\%/\$__args\{$1\}/gx ) {
|
|
print "## ExpandArgStr: $_\n" if $DEBUG_EXPAND;
|
|
}
|
|
}
|
|
|
|
#
|
|
# replace <foo> set refs with a lookup.
|
|
#
|
|
&ExpandSetRef();
|
|
|
|
$rest = $rest . " " . $_;
|
|
@BalParen = FindBalParens($rest);
|
|
}
|
|
|
|
if ($BalParen[0] < 0) {
|
|
EmitError($_, "Unbalanced right paren");
|
|
return ("", $rest);
|
|
}
|
|
|
|
$ParamStr = $BalParen[1];
|
|
$rest = $BalParen[2];
|
|
|
|
$ParamStr =~ s/^\s*\(\s*\/*//; # remove " ( /"
|
|
$ParamStr =~ s/\s*\)\s*$//; # remove " ) "
|
|
|
|
return ($ParamStr, $rest);
|
|
}
|
|
|
|
|
|
|
|
sub EmitCode {
|
|
my $ArgStr;
|
|
|
|
foreach $ArgStr (@_) {
|
|
print $ArgStr;
|
|
}
|
|
}
|
|
|
|
|
|
sub EmitComment {
|
|
my $ArgStr;
|
|
|
|
return if !$DEBUG_CODE;
|
|
foreach $ArgStr (@_) {
|
|
print "## ", $ArgStr, "\n";
|
|
}
|
|
}
|
|
|
|
|
|
sub EmitError {
|
|
my $input = shift;
|
|
my $msg = shift;
|
|
|
|
print STDOUT "ERROR: $main::InFile($main::inlinenumber) - $msg '", $input, "'\n";
|
|
print STDERR "ERROR: $main::InFile($main::inlinenumber) - $msg '", $input, "'\n";
|
|
}
|
|
|
|
|
|
|
|
|
|
sub CompileFrsObject {
|
|
my $func = shift;
|
|
my ($lhs, $rest, @pars, $ParamStr, $p, $expansion, $switch, $rhs, @setnames, $argtype);
|
|
|
|
#
|
|
# Consume input until we have text with balanced parens.
|
|
#
|
|
($lhs, $rest) = m/(.*)$func\s*(.*)/;
|
|
|
|
($ParamStr, $rest) = ExtractParams($rest);
|
|
if ($ParamStr eq "") {
|
|
EmitError("FRS object, no parameters found near: '$func' ");
|
|
exit;
|
|
}
|
|
|
|
print "## '$ParamStr' \n" if $DEBUG_PARSE;
|
|
|
|
if ($FRS_CALLS{$func}->{NSETS} != 0) {
|
|
$expansion = '$__HashRef = ' . $FRS_CALLS{$func}->{INTRO};
|
|
EmitCode " $expansion \n";
|
|
} else {
|
|
EmitCode " $FRS_CALLS{$func}->{INTRO} \n";
|
|
}
|
|
|
|
@pars = &ParseArgList($ParamStr);
|
|
print "\n\n", "## ", join(':', (@pars)), "\n\n" if $DEBUG_EXPAND;
|
|
|
|
$expansion = '';
|
|
foreach $p (@pars) {
|
|
$expansion .= &ExpandSwitch($func, $p) . ", ";
|
|
}
|
|
#
|
|
# Check for inline call and remove the keys.
|
|
# **NOTE** if any inline func takes more than 1 arg then add code
|
|
# to place the args in the order specified by $FRS_CALLS{$func}->{ARGS}
|
|
# using the arg name in the key part.
|
|
#
|
|
if ($FRS_CALLS{$func}->{CALL} == 2) {
|
|
$expansion =~ s/\w+=>//g; #for now just remove key part.
|
|
}
|
|
|
|
substr($expansion, -2, 1) = ''; # remove trailing comma-space
|
|
|
|
EmitCode " ".$expansion ;
|
|
|
|
EmitCode "\n $FRS_CALLS{$func}->{CLOSE} \n";
|
|
|
|
if ($FRS_CALLS{$func}->{NSETS} != 0) {
|
|
$lhs = &Trim($lhs);
|
|
$lhs =~ s/\s*:\s*/ /g;
|
|
@setnames = split('\s', $lhs);
|
|
foreach $p (@setnames) {
|
|
#
|
|
# Add set def and remember for cleanup if we are inside a SubDef.
|
|
#
|
|
EmitCode ' &FRSSUP::AddToSet("', $p, '", $__HashRef);', "\n";
|
|
if ($SubDefActive) {push @SubDefCleanup, $p;}
|
|
}
|
|
}
|
|
|
|
EmitCode "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
sub CompileFrsSubDef {
|
|
my $func = shift;
|
|
my ($SubName, $rest, @pars, $p, $expansion, $switch, $rhs, @setnames, $argtype);
|
|
my (@SubBody, @BalBrace, $ParamStr);
|
|
|
|
#
|
|
# Consume input until we have text with balanced parens.
|
|
#
|
|
($SubName, $rest) = m/(?:.*?)(?:$func)+? \s* (\w+?) \s* (\(.*)/x;
|
|
EmitComment( "subname = '$SubName', func = '$func', rest = '$rest'\n");
|
|
|
|
if (exists $FRS_CALLS{$SubName}) {
|
|
EmitError("FRS_SUB subroutine name: '$SubName' ",
|
|
"Conflict with builtin or previously defined name.");
|
|
exit;
|
|
}
|
|
|
|
($ParamStr, $rest) = ExtractParams($rest);
|
|
if ($ParamStr eq "") {
|
|
EmitError("FRS_SUB no parameters found near: '$SubName' ");
|
|
exit;
|
|
}
|
|
|
|
#
|
|
# Add the function name to the call table.
|
|
#
|
|
$FRS_CALLS{$SubName} = { CALL=>1, NSETS=>0,
|
|
INTRO=>"&$SubName (",
|
|
CLOSE=>');',
|
|
ARGS=>[], BODY=>[] };
|
|
|
|
EmitCode("sub $SubName {\n");
|
|
EmitCode(' my %__args = (@_);' . "\n");
|
|
|
|
EmitCode(' my ($__HashRef, $__k, $__v);' . "\n");
|
|
if ($DEBUG_CHECK) {
|
|
EmitCode(' print "##\n";' . "\n");
|
|
EmitCode(' print "## Entering sub ' . $SubName . '\n";' . "\n");
|
|
EmitCode(' while ( ($__k, $__v) = each %__args ) { print "## \t$__k => \'$__v\'\n"; }' . "\n");
|
|
}
|
|
EmitCode("\n\n");
|
|
|
|
#EmitComment( " paramstr: $ParamStr\n");
|
|
|
|
@pars = &ParseArgList($ParamStr);
|
|
#EmitComment( join(':', (@pars)) . "\n\n");
|
|
|
|
$expansion = '';
|
|
foreach $p (@pars) {
|
|
($switch, $rhs) = FRSSUP::ParseSwitch($p);
|
|
if ((!defined($rhs)) || (!exists $FRS_ARG_TYPES{$rhs})) {
|
|
EmitError("FRS_SUB parameter: '$p' ",
|
|
"Right hand side must have valid type code in FRS_SUB declaration");
|
|
}
|
|
|
|
if (exists $FRS_ARGS{$SubName."-".$switch}) {
|
|
EmitError("FRS_SUB parameter: '$SubName-$switch' ",
|
|
"Conflict with builtin or previously defined name.");
|
|
exit;
|
|
}
|
|
#
|
|
# Add this parameter to the argument table.
|
|
#
|
|
$FRS_ARGS{$SubName."-".$switch} = { TYPE => "$rhs" };
|
|
|
|
#EmitComment("new FRS_SUB parameter: '$SubName-$switch' ");
|
|
|
|
push @{ $FRS_CALLS{$SubName}{ARGS} }, $switch;
|
|
}
|
|
|
|
if ($SubList ne '') {$SubList .= "|";}
|
|
$SubList .= $SubName;
|
|
#EmitComment( "new sublist = '$SubList'\n");
|
|
|
|
$_ = $rest;
|
|
|
|
EmitCode "\n";
|
|
|
|
return 1; #we are now compiling in a subdef.
|
|
}
|
|
|
|
|
|
|
|
sub CompileFrsEndSubDef {
|
|
my $func = shift;
|
|
my ($p);
|
|
|
|
#
|
|
# Consume input up through FRS_END_SUB
|
|
#
|
|
s/(?:.*?)(?:$func)+? \s*//x;
|
|
|
|
#
|
|
# Emit code to free the locally defined sets.
|
|
#
|
|
foreach $p (@SubDefCleanup) {
|
|
EmitCode(' &FRSSUP::DeleteSet("' . $p . '");'. "\n");
|
|
}
|
|
|
|
EmitCode ("} # FRS_END_SUB\n\n\n");
|
|
undef @SubDefCleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub CompileFrsFunctionCall {
|
|
my $func = shift;
|
|
my ($lhs, $rest, @pars, $p, $ParamStr, $expansion, $switch, $rhs, @setnames, $argtype);
|
|
|
|
#
|
|
# Consume input until we have text with balanced parens.
|
|
#
|
|
($lhs, $rest) = m/(.*?)(?:$func)+?\s*(.*)/x;
|
|
#print "\n lhs = '$lhs', func = '$func', rest = '$rest'\n";
|
|
|
|
($ParamStr, $rest) = ExtractParams($rest);
|
|
if ($ParamStr eq "") {
|
|
EmitError("FRS_FUNC no parameters found near: '$func' ");
|
|
exit;
|
|
}
|
|
|
|
print "## '$ParamStr' \n" if $DEBUG_PARSE;
|
|
|
|
if ($FRS_CALLS{$func}->{NSETS} ne 0) {
|
|
EmitError($func, "Internal error - Function {NSETS} ne 0");
|
|
exit;
|
|
} else {
|
|
EmitCode "$lhs $FRS_CALLS{$func}->{INTRO} \n";
|
|
}
|
|
|
|
@pars = &ParseArgList($ParamStr);
|
|
print "\n\n", "## ", join(':', (@pars)), "\n\n" if $DEBUG_EXPAND;
|
|
|
|
$expansion = '';
|
|
foreach $p (@pars) {
|
|
$expansion .= &ExpandSwitch($func, $p) . ", ";
|
|
}
|
|
#
|
|
# Check for inline call and remove the keys.
|
|
# **NOTE** if any inline func takes more than 1 arg then add code
|
|
# to place the args in the order specified by $FRS_CALLS{$func}->{ARGS}
|
|
# using the arg name in the key part.
|
|
#
|
|
if ($FRS_CALLS{$func}->{CALL} == 2) {
|
|
$expansion =~ s/\w+=>//g; #for now just remove key part.
|
|
}
|
|
|
|
substr($expansion, -2, 1) = ''; # remove trailing comma-space
|
|
|
|
EmitCode $expansion ;
|
|
|
|
EmitCode "$FRS_CALLS{$func}->{CLOSE} \n";
|
|
EmitCode "\n";
|
|
|
|
$_ = $rest;
|
|
}
|
|
|
|
|
|
sub ExpandSetRef {
|
|
#
|
|
# IMPROVEMENT: Don't apply inside "".
|
|
# works on $_
|
|
#
|
|
# First convert <foo>[x] to <foo>->[x]
|
|
#
|
|
if ( s/(\w) > \s* \[/$1>->[/gx ) {
|
|
print "## ExpandSetRefIndex: $_\n" if $DEBUG_EXPAND;
|
|
}
|
|
|
|
#
|
|
# replace set refs with a lookup.
|
|
# scan for <foo> or <$foo> or <"foo"> or <'foo'>
|
|
# No embedded whitespace allowed.
|
|
# replace with {&FRSSUP::SelectSet($arg)}
|
|
#
|
|
if ( s/< ([\$\"\']?? \w+) >/&FRSSUP::SelectSet\($1\)/gx ) {
|
|
print "## ExpandSetRef: $_\n" if $DEBUG_EXPAND;
|
|
}
|
|
}
|
|
|
|
|
|
sub ExpandSwitch {
|
|
my $SubName = shift;
|
|
my $input = shift;
|
|
my ($switch, $rhs, $argtype, $ArgIndex, $indexpart, $setpart);
|
|
## my $FoundFormalPar;
|
|
|
|
my $result = '';
|
|
|
|
#
|
|
# Process the argument string "switch=rhs" based on the argtype def.
|
|
#
|
|
($switch, $rhs) = FRSSUP::ParseSwitch($input);
|
|
|
|
|
|
if (($main::SubList ne '') && ($SubName =~ m/$main::SubList/)) {
|
|
$ArgIndex = $SubName."-".$switch; # The arg index for a user defined function.
|
|
EmitComment("ArgIndex for parameter: '$ArgIndex' ") if $DEBUG_EXPAND;
|
|
} else {
|
|
$ArgIndex = $switch; # The arg index for a builtin function.
|
|
EmitComment("ArgIndex for parameter: '$switch' ") if $DEBUG_EXPAND;
|
|
}
|
|
#
|
|
# Get the switch argument type. default to a string.
|
|
#
|
|
if (exists $FRS_ARGS{$ArgIndex}) {
|
|
$argtype = $FRS_ARGS{$ArgIndex}->{TYPE};
|
|
EmitComment("ArgType found for parameter: '$ArgIndex' is '$argtype'") if $DEBUG;
|
|
} else {
|
|
$argtype = 'VALUE_STR';
|
|
}
|
|
|
|
|
|
#
|
|
# SET_REF_SINGLE
|
|
# SET_REF_SET
|
|
# SET_ELEMENT
|
|
# SCHEDULE
|
|
# ARG_REF
|
|
# VALUE_INT
|
|
# VALUE_CHOICE_SINGLE
|
|
# VALUE_CHOICE_LIST
|
|
# VALUE_STR
|
|
# VALUE_SIGN_TIME
|
|
# VALUE_TIME_SINGLE
|
|
# VALUE_TIME_LIST
|
|
# VARCON
|
|
#
|
|
|
|
$result = $rhs;
|
|
if (($argtype eq 'SET_ELEMENT') || ($argtype eq 'SCHEDULE')) {
|
|
#
|
|
# /ARG=<HUB> maps to /ARG=&SelectSet("HUB")->[0]
|
|
# /ARG=<HUB>[expr] maps to &SelectSet("HUB")->[expr]
|
|
# anything else is unchanged.
|
|
#
|
|
### goto RETURN if ($FoundFormalPar);
|
|
|
|
goto RETURN if (($argtype eq 'SCHEDULE') && ($rhs =~ m/\^s*(ON|OFF)\s*$/i));
|
|
|
|
if ($rhs =~ m/SelectSet\(.*\)$/) { $rhs .= '->[0]'; }
|
|
|
|
$result = $rhs;
|
|
|
|
# ($setpart, $indexpart) = $rhs =~ m/([^\[]*) (.*)/x ;
|
|
# $result = $FRS_ARG_TYPES{$argtype}->{INTRO} .
|
|
# $setpart .
|
|
# $FRS_ARG_TYPES{$argtype}->{CLOSE} .
|
|
# $indexpart;
|
|
goto RETURN;
|
|
|
|
|
|
} elsif ($argtype eq 'SET_REF_SET') {
|
|
## goto RETURN if ($FoundFormalPar);
|
|
|
|
$result = $FRS_ARG_TYPES{$argtype}->{INTRO} .
|
|
$rhs .
|
|
$FRS_ARG_TYPES{$argtype}->{CLOSE};
|
|
goto RETURN;
|
|
|
|
} elsif ($argtype eq 'SET_REF_SINGLE') {
|
|
} elsif ($argtype eq 'ARG_REF') {
|
|
} elsif ($argtype eq 'VALUE_CHOICE_SINGLE') {
|
|
} elsif ($argtype eq 'VALUE_CHOICE_LIST') {
|
|
|
|
} elsif (($argtype eq 'VALUE_STR') ||
|
|
($argtype eq 'VARCON')) {
|
|
|
|
#
|
|
# The following is a bad idea.
|
|
# Consider "D:\"
|
|
# When searching for balanced parens the backslash escapes the dbl-quote
|
|
# so the trailing paren ends up as part of a quoted string.
|
|
# if you double up the backslash then the line below will give you
|
|
# some more. So the upshot is make the user double the backslash.
|
|
#
|
|
#$rhs =~ s/\\(?=[^\\])/\\\\/g; # double up the backslash
|
|
$result = $FRS_ARG_TYPES{$argtype}->{INTRO} .
|
|
$rhs .
|
|
$FRS_ARG_TYPES{$argtype}->{CLOSE};
|
|
goto RETURN;
|
|
|
|
} elsif (($argtype eq 'VALUE_INT') ||
|
|
($argtype eq 'VALUE_SIGN_TIME') ||
|
|
($argtype eq 'VALUE_TIME_SINGLE') ||
|
|
($argtype eq 'VALUE_TIME_LIST')) {
|
|
$result = $FRS_ARG_TYPES{$argtype}->{INTRO} .
|
|
$rhs .
|
|
$FRS_ARG_TYPES{$argtype}->{CLOSE};
|
|
goto RETURN;
|
|
|
|
} elsif ($argtype eq 'VALUE_BOOL') {
|
|
$result = 'TRUE';
|
|
$rhs = 'TRUE';
|
|
goto RETURN;
|
|
|
|
} else {
|
|
&EmitError("ExpandSwitch('$SubName','$input')", "Unexpected internal error");
|
|
}
|
|
|
|
|
|
RETURN:
|
|
|
|
EmitComment(" '$switch' = '$rhs' arg_typ: $argtype result: $result");
|
|
|
|
return $switch . "=>" . $result;
|
|
}
|
|
|
|
|
|
|
|
sub ProcessFile {
|
|
my ($modtime, $func);
|
|
my ($newfile, $evalstr);
|
|
local *F;
|
|
local *inlinenumber;
|
|
local *InFile;
|
|
|
|
($InFile) = @_;
|
|
open(F, $InFile) || die "Can't open input file: $InFile\n";
|
|
$modtime = (stat $InFile)[9];
|
|
EmitComment("Processing file $InFile Modify Time: " . scalar localtime($modtime) . "\n\n");
|
|
$infilelist = $infilelist . " " . $InFile;
|
|
$inlinenumber = 0;
|
|
|
|
while (<F>) {
|
|
$inlinenumber++;
|
|
chop;
|
|
|
|
LOOP:
|
|
next if (m/^\s*$|^#/); # remove blank lines and lines starting with #
|
|
|
|
if (m/\#/) {$_ = CleanInput($_)}; # remove trailing comment string.
|
|
|
|
next if (m/^\s*$/);
|
|
&EmitComment ($_);
|
|
|
|
#
|
|
# Check for an include directive.
|
|
# The parameter value gets EVALed.
|
|
#
|
|
# .FRS_INCLUDE ($CMD_VARS{"SERVERS"})
|
|
# This lets you pass the file name on cmd line with -DSERVERS=filename
|
|
#
|
|
# .FRS_INCLUDE ("genbchoff.srv")
|
|
# This lets you include a specific file.
|
|
#
|
|
if (m/\.FRS_INCLUDE/) {
|
|
($evalstr) = m/\.FRS_INCLUDE\s*\(\s*(.+)\s*\)$/;
|
|
$newfile = eval $evalstr;
|
|
if ($newfile ne "") {ProcessFile($newfile);}
|
|
next;
|
|
}
|
|
|
|
#
|
|
# .FRS_EVAL( single line perl expresion evaluated at config file compile time )
|
|
#
|
|
# For example, the following checks for the presence of a required compile time parameter.
|
|
#
|
|
# .FRS_EVAL (if (!exists $CMD_VARS{"SERVERS"}) {print STDERR "ERROR - Required parameter -DSERVERS=filename not found."; exit} )
|
|
#
|
|
if (m/\.FRS_EVAL/) {
|
|
($evalstr) = m/\.FRS_EVAL\s*\(\s*(.+)\s*\)$/;
|
|
eval $evalstr;
|
|
next;
|
|
}
|
|
|
|
#
|
|
# If we are in a DEFSUB then scan for calling params replacement strings.
|
|
# If found then insert a ref to __args hash.
|
|
#
|
|
if ($SubDefActive) {
|
|
if ( s/\%(\w+)\%/\$__args\{$1\}/gx ) {
|
|
print "## ExpandArgStr: $_\n" if $DEBUG_EXPAND;
|
|
}
|
|
#if ($FoundFormalPar) {
|
|
# #
|
|
# # look for component dereference "->" and replace with {}
|
|
# #
|
|
# $rhs =~ s/->(\w+)/->\{$1\}/gx;
|
|
#}
|
|
}
|
|
|
|
#
|
|
# replace <foo> set refs with a lookup.
|
|
#
|
|
&ExpandSetRef();
|
|
|
|
#
|
|
# Check for FRS object declaration
|
|
#
|
|
if (($func) = m/($FrsObjectNames)/xio) {
|
|
CompileFrsObject($func);
|
|
next;
|
|
}
|
|
|
|
#
|
|
# Check for FRS function call
|
|
#
|
|
while (($func) = m/($FrsFunctionNames)/xio) {
|
|
CompileFrsFunctionCall($func);
|
|
}
|
|
|
|
#
|
|
# Check for FRS function definition
|
|
#
|
|
if (($func) = m/(FRS_SUB)/xi) {
|
|
if ($SubDefActive) {
|
|
EmitError("$_\n", "Recursive SUB DEF not allowed.\n");
|
|
exit;
|
|
}
|
|
#
|
|
# build the header and update the symbol table with the arg type
|
|
# definitions. Then continue compiling the body.
|
|
#
|
|
$SubDefActive = CompileFrsSubDef($func);
|
|
next if ($_ eq '');
|
|
goto LOOP;
|
|
}
|
|
|
|
#
|
|
# Check for end of FRS function definition
|
|
#
|
|
if (($func) = m/(FRS_END_SUB)/xi) {
|
|
if (!$SubDefActive) {
|
|
EmitError("$_\n", "FRS_END_SUB found while no SUB DEF active.\n");
|
|
exit;
|
|
}
|
|
#
|
|
# Generate the cleanup code and end the function.
|
|
#
|
|
CompileFrsEndSubDef($func);
|
|
$SubDefActive = 0;
|
|
next if ($_ eq '');
|
|
goto LOOP;
|
|
}
|
|
|
|
#
|
|
# Check for user defined object declaration
|
|
#
|
|
if (($main::SubList ne '') && (($func) = m/($main::SubList)/)) {
|
|
|
|
CompileFrsFunctionCall($func);
|
|
next;
|
|
}
|
|
|
|
EmitCode($_."\n");
|
|
|
|
}
|
|
close(F);
|
|
}
|
|
|
|
|
|
|
|
my $USAGE = "
|
|
|
|
Usage: $0 [cmd options] infiles... \> output
|
|
Process the FRS replica set definition file(s) and generate a perl output
|
|
file that when executed creates the desired configuration in the DS.
|
|
|
|
Command line options must be prefixed with a dash.
|
|
|
|
-verbose=all : display all debug output.
|
|
-verbose=code : display input interspersed with output. Note that the
|
|
resulting output file may not run. For debugging.
|
|
-verbose=check : Add some check code to print out argument values.
|
|
-verbose=parse : display parsing results. For debugging.
|
|
-verbose=expand : display variable expansion results. For debugging.
|
|
|
|
To add a help message to the generated script add a usage string and then
|
|
insert the following function call in the input script.
|
|
|
|
FRSSUP::CheckForHelp(\%CMD_PARS, \\\$usage);
|
|
|
|
where the usage string might look like:
|
|
\$usage = \"
|
|
The input options to this script are:
|
|
-DBchID=nnnnn : to provide a value for the BchID parameter.
|
|
...\";
|
|
|
|
To pass the values of command line paramters to your script use the notation
|
|
-Dvarname=value on the command line when invoking the generated script.
|
|
e.g. perl generated_script.prl -DBchID=0011220
|
|
|
|
The input script can retrieve the value with the reference \$CMD_VARS{\"varname\"}.
|
|
varname is case sensitive. In the example, \$CMD_VARS{\"BchID\"}.
|
|
|
|
Other command line options can be retrived by the script using
|
|
\$CMD_PARS{\"optionname\"} where optionname is in lower case.
|
|
|
|
";
|
|
|
|
my ($k, $v, $k1, $v1, $HashRef, $str, $lhs, $rhs, $filename);
|
|
|
|
&FRSSUP::ProcessCmdLine(\%CMD_VARS, \%CMD_PARS);
|
|
|
|
die $USAGE unless @ARGV;
|
|
$k = @rem; # here to suppress warning message on @rem.
|
|
|
|
$argdebug = lc($CMD_PARS{"verbose"});
|
|
if ($argdebug ne "") {
|
|
if ($argdebug =~ m/code/) {$DEBUG_CODE=1;}
|
|
if ($argdebug =~ m/all/) {$DEBUG=1; $DEBUG_PARSE=1; $DEBUG_EXPAND=1; $DEBUG_CHECK=1; $DEBUG_CODE=1;}
|
|
if ($argdebug =~ m/check/) {$DEBUG_CHECK=1;}
|
|
if ($argdebug =~ m/parse/) {$DEBUG_PARSE=1;}
|
|
if ($argdebug =~ m/expand/) {$DEBUG_EXPAND=1;}
|
|
if (($DEBUG + $DEBUG_CODE + $DEBUG_CHECK + $DEBUG_PARSE + $DEBUG_EXPAND) == 0) {
|
|
print STDERR "Error: Invalid -verbose parameter: $argdebug\n";
|
|
die $USAGE;
|
|
}
|
|
}
|
|
|
|
|
|
$infilelist = '';
|
|
|
|
$inlinenumber = 0;
|
|
$InFile = "";
|
|
|
|
EmitCode(' use frsobjsup;' . "\n");
|
|
|
|
EmitCode(' package main; ' . "\n");
|
|
EmitCode(' my ($__HashRef, $__k, $__v);' . "\n");
|
|
|
|
|
|
EmitCode(' my (%CMD_VARS, %CMD_PARS);' . "\n\n");
|
|
EmitCode(' &FRSSUP::ProcessCmdLine(\%CMD_VARS, \%CMD_PARS);' . "\n\n");
|
|
|
|
|
|
foreach $filename (@ARGV) {
|
|
ProcessFile($filename);
|
|
}
|
|
|
|
#while (<>) {
|
|
#
|
|
# if ($InFile ne $ARGV) {
|
|
# $InFile = $ARGV;
|
|
# $modtime = (stat $InFile)[9];
|
|
# EmitComment("Processing file $InFile Modify Time: " . scalar localtime($modtime) . "\n\n");
|
|
# $infilelist = $infilelist . " " . $InFile;
|
|
# $inlinenumber = 0;
|
|
# }
|
|
# $inlinenumber++;
|
|
#
|
|
# chop;
|
|
#}
|
|
|
|
|
|
|
|
EmitCode('__END__' . "\n");
|
|
|
|
|
|
exit;
|
|
|
|
|
|
|
|
#
|
|
# Todo:
|
|
#
|
|
# Implement CHOICES type and checking
|
|
# error check argument names and validate operand types.
|
|
# Add error checking with line numbers $ errors going to stderr.
|
|
# test with malformed input, e.g. missing rhs, missing (, missing ), etc.
|
|
# wrap invocation in an EVAL
|
|
#
|
|
# write func to wrap long lines for comment print.
|
|
# Write help and doc. give some examples of simple perl script commands.
|
|
# Provide runtime option to start the service on any new member.
|
|
#
|
|
# Implement set operations e.g.
|
|
# INSTALLED_BCH: FRS_SET_DIFF(/ARG1=BCH /ARG2=NOTDEPLOYED)
|
|
#
|
|
|
|
|
|
__END__
|
|
:endofperl
|
|
@rem -d -w
|
|
@perl -w %~dpn0.cmd %*
|
|
@goto :QUIT
|
|
@:QUIT
|