use strict;
use warnings;
#
# WMLScript Language Specification Version 1.1
#
package WAP::wmls::node;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless $self, $class;
my ($op) = @_;
$self->{OpCode} = $op;
$self->{Next} = undef;
$self->{Prev} = undef;
$self->{Last} = $self;
$self->{Deleted} = 0;
return $self;
}
sub del {
my $self = shift;
$self->{Deleted} = 1;
$self->{OpCode}->{Deleted} = 1;
return $self;
}
sub configure {
my $self = shift;
$self->{OpCode}->configure(@_);
return $self;
}
sub concat {
my $node1 = shift;
my ($node2) = @_;
$node1->{Last}->{Next} = $node2;
$node2->{Prev} = $node1->{Last};
$node1->{Last} = $node2->{Last};
return $node1;
}
sub insert {
my $node1 = shift;
my ($node2) = @_;
$node2->{Next} = $node1->{Next};
$node2->{Prev} = $node1;
if (defined $node1->{Next}) {
$node1->{Next}->{Prev} = $node2;
}
$node1->{Next} = $node2;
return;
}
sub visit {
my $self = shift;
my $visitor = shift;
for (my $node = $self; defined $node; $node = $node->{Next}) {
my $opcode = $node->{OpCode};
my $class = ref $opcode;
my $func = 'visit' . substr($class, rindex($class, ':') + 1);
$visitor->$func($opcode, @_);
}
return;
}
sub visitActive {
my $self = shift;
my $visitor = shift;
for (my $node = $self; defined $node; $node = $node->{Next}) {
next if ($node->{Deleted});
my $opcode = $node->{OpCode};
my $class = ref $opcode;
my $func = 'visit' . substr($class, rindex($class, ':') + 1);
$visitor->$func($opcode, @_);
}
return;
}
sub getFirstActive {
my $self = shift;
my $node;
for ( $node = $self;
defined($node) and $node->{Deleted};
$node = $node->{Next} ) {}
return $node;
}
sub getLastActive {
my $self = shift;
my $node;
for ( $node = $self->{Last};
defined($node->{Next});
$node = $node->{Next} ) {}
for ( ;
defined($node) and $node->{Deleted};
$node = $node->{Prev} ) {}
return $node;
}
sub getNextActive {
my $self = shift;
my $node;
for ( $node = $self->{Next};
defined($node) and $node->{Deleted};
$node = $node->{Next} ) {}
return $node;
}
sub getPrevActive {
my $self = shift;
my $node;
for ( $node = $self->{Prev};
defined $node and $node->{Deleted};
$node = $node->{Prev} ) {}
return $node;
}
###############################################################################
package WAP::wmls::OpCode;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $parser = shift;
my %attr = @_;
my $self = \%attr;
foreach (keys %attr) {
unless (defined $self->{$_}) {
delete $self->{$_};
}
}
$self->{Lineno} = $parser->YYData->{lineno};
return $self;
}
sub isa {
my $self = shift;
my ($type) = @_;
return UNIVERSAL::isa($self, 'WAP::wmls::' . $type);
}
sub configure {
my $self = shift;
my %attr = @_;
while ( my ($key, $value) = each(%attr) ) {
if (defined $value) {
$self->{$key} = $value;
}
}
return $self;
}
package WAP::wmls::Url;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::AccessDomain;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::AccessPath;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::MetaName;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::MetaHttpEquiv;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::MetaUserAgent;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Function;
use base qw(WAP::wmls::OpCode);
use Carp;
use constant UINT8_MAX => 255;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $parser = shift;
my $self = new WAP::wmls::OpCode($parser, @_);
bless $self, $class;
# specific
$self->_SetNbArg($parser);
if (defined $self->{Value}) {
$self->_CheckBreakContinue($parser, $self->{Value});
}
else {
$parser->Warning("function without statement.\n");
}
$parser->YYData->{symbtab_var}->Check();
return new WAP::wmls::node($self);
}
sub _SetNbArg {
my $self = shift;
my ($parser) = @_;
my $def = $self->{Definition};
if (defined $self->{Param}) {
my $nbargs = $self->{Param}->{OpCode}->{Index};
if ($nbargs >= UINT8_MAX) {
$parser->Error("too many function parameter.");
}
else {
$def->{NumberOfArguments} = $nbargs;
}
}
else {
$def->{NumberOfArguments} = 0;
}
return;
}
sub _CheckBreakContinue {
my $self = shift;
my ($parser, $block) = @_;
for (my $node = $block; defined $node; $node = $node->{Next}) {
my $opcode = $node->{OpCode};
if ( $opcode->isa('Jump')
and !defined $opcode->{Definition} ) {
my $type = $opcode->{TypeDef};
if ($type eq 'LABEL_CONTINUE') {
$parser->Error("continue without loop.\n");
}
elsif ($type eq 'LABEL_BREAK') {
$parser->Error("break without loop.\n");
}
else {
croak "INTERNAL_ERROR: _CheckBreakContinue\n";
}
}
}
return;
}
package WAP::wmls::Argument;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::LoadVar;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::StoreVar;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::IncrVar;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::DecrVar;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::AddAsg;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::SubAsg;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Label;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Pop;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::ToBool;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::ScOr;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::ScAnd;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Return;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::ReturnES;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Call;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::CallLib;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::CallUrl;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::Jump;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::FalseJump;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::UnaryOp;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::BinaryOp;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
package WAP::wmls::LoadConst;
use base qw(WAP::wmls::OpCode);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::OpCode(@_);
bless $self, $class;
return new WAP::wmls::node($self);
}
###############################################################################
package WAP::wmls::printVisitor;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless $self, $class;
$self->{level} = 0;
return $self;
}
sub printLabel {
my ($level, $deleted, $label) = @_;
print '~'
if ($deleted);
while ($level--) {
print "\t";
}
print $label;
return;
}
sub printDefn {
my ($def) = @_;
if (defined $def) {
print " $def->{Symbol}\n";
}
else {
print " null\n";
}
return;
}
sub printOp {
my ($op) = @_;
print " $op\n";
return;
}
sub printConst {
my ($typedef, $value) = @_;
if ($typedef eq 'TYPE_INTEGER') {
print " $value\n";
}
elsif ($typedef eq 'TYPE_FLOAT') {
print " $value\n";
}
elsif ($typedef eq 'TYPE_STRING') {
print " $value\n";
}
elsif ($typedef eq 'TYPE_UTF8_STRING') {
print " $value\n";
}
elsif ($typedef eq 'TYPE_BOOLEAN') {
if ($value) {
print " true\n";
}
else {
print " false\n";
}
}
elsif ($typedef eq 'TYPE_INVALID') {
print " INVALID\n";
}
else {
print "type incompatible of CONST\n";
}
return;
}
sub visitUrl {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "URL");
printDefn($opcode->{Definition});
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitAccessDomain {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "ACCESS DOMAIN\n");
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitAccessPath {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "ACCESS PATH\n");
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitMetaName {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "META NAME\n");
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitMetaHttpEquiv {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "META HTTP EQUIV\n");
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitMetaUserAgent {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "META USER AGENT\n");
$self->{level} ++;
$opcode->{Value}->visit($self);
$self->{level} --;
return;
}
sub visitFunction {
my $self = shift;
my ($opcode) = @_;
printf("\n");
my $def = $opcode->{Definition};
if ($def->{Type} eq 'PRIVATE_FUNC') {
printLabel($self->{level}, 0, "FUNCTION");
}
elsif ($def->{Type} eq 'PUBLIC_FUNC') {
printLabel($self->{level}, 0, "EXTERN FUNCTION");
}
else {
print "Incompatible type of FUNC\n";
}
printDefn($def);
$self->{level} ++;
$opcode->{Param}->visit($self)
if (defined $opcode->{Param});
$opcode->{Value}->visit($self)
if (defined $opcode->{Value});
$self->{level} --;
return;
}
sub visitArgument {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, 0, "ARG");
printDefn($opcode->{Definition});
return;
}
sub visitLoadVar {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "LOAD_VAR");
printDefn($opcode->{Definition});
return;
}
sub visitStoreVar {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "STORE_VAR");
printDefn($opcode->{Definition});
return;
}
sub visitIncrVar {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "INCR_VAR");
printDefn($opcode->{Definition});
return;
}
sub visitDecrVar {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "DECR_VAR");
printDefn($opcode->{Definition});
return;
}
sub visitAddAsg {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "ADD_ASG");
printDefn($opcode->{Definition});
return;
}
sub visitSubAsg {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "SUB_ASG");
printDefn($opcode->{Definition});
return;
}
sub visitLabel {
my $self = shift;
my ($opcode) = @_;
printLabel(0, $opcode->{Deleted}, "LABEL\t");
printDefn($opcode->{Definition});
return;
}
sub visitPop {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "POP\n");
return;
}
sub visitToBool {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "TOBOOL\n");
return;
}
sub visitScOr {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "SCOR\n");
return;
}
sub visitScAnd {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "SCAND\n");
return;
}
sub visitReturn {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "RETURN\n");
return;
}
sub visitReturnES {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "RETURN_ES\n");
return;
}
sub visitCall {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "CALL");
printDefn($opcode->{Definition});
return;
}
sub visitCallLib {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "CALL_LIB");
printDefn($opcode->{Definition});
return;
}
sub visitCallUrl {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "CALL_URL");
printDefn($opcode->{Definition});
return;
}
sub visitJump {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "JUMP\t\t");
printDefn($opcode->{Definition});
return;
}
sub visitFalseJump {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "FALSE_JUMP\t");
printDefn($opcode->{Definition});
return;
}
sub visitUnaryOp {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "UNOP");
printOp($opcode->{Operator});
return;
}
sub visitBinaryOp {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "BINOP");
printOp($opcode->{Operator});
return;
}
sub visitLoadConst {
my $self = shift;
my ($opcode) = @_;
printLabel($self->{level}, $opcode->{Deleted}, "LOAD_CONST");
printConst($opcode->{TypeDef}, $opcode->{Value});
return;
}
###############################################################################
package WAP::wmls::defn;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless $self, $class;
my ($symb, $type) = @_;
$self->{Symbol} = $symb;
$self->{Type} = $type if (defined $type);
$self->{ID} = 0xffff;
$self->{NbUse} = 0;
return $self;
}
###############################################################################
package WAP::wmls::SymbTab;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my ($parser) = @_;
my $self = {};
bless $self, $class;
$self->{parser} = $parser;
$self->{tab} = {};
return $self;
}
sub Insert {
my $self = shift;
my ($symb, $def) = @_;
if (exists $self->{tab}{$symb}) {
$self->{parser}->Error("Redefinition - $symb.\n");
}
else {
$self->{tab}{$symb} = $def;
}
return;
}
###############################################################################
package WAP::wmls::SymbTabVar;
use base qw(WAP::wmls::SymbTab);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::SymbTab(@_);
bless $self, $class;
return $self;
}
sub InsertLocal {
my $self = shift;
my ($symb) = @_;
my $def = new WAP::wmls::defn($symb);
$def->{NbUse} ++;
$self->SUPER::Insert($symb, $def);
return $def;
}
sub InsertArg {
my $self = shift;
my ($symb, $num) = @_;
my $def = new WAP::wmls::defn($symb);
$def->{ID} = $num;
$self->SUPER::Insert($symb, $def);
return $def;
}
sub Lookup {
my $self = shift;
my ($symb) = @_;
if (exists $self->{tab}{$symb}) {
my $def = $self->{tab}{$symb};
$def->{NbUse} ++;
return $def;
}
else {
$self->{parser}->Error("Variable undefined - $symb.\n");
return;
}
}
sub Check {
my $self = shift;
foreach (keys %{$self->{tab}}) {
my $def = $self->{tab}{$_};
unless ($def->{NbUse}) {
$self->{parser}->Warning("Unused variable - $_.\n");
}
}
$self->{tab} = {};
return;
}
###############################################################################
package WAP::wmls::SymbTabLib;
use base qw(WAP::wmls::SymbTab);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::SymbTab(@_);
bless $self, $class;
return $self;
}
sub Lookup {
my $self = shift;
my ($library) = @_;
unless (exists $self->{tab}{$library}) {
$self->{parser}->Error("Library unknown - $library.\n");
return;
}
return 1;
}
###############################################################################
package WAP::wmls::SymbTabFunc;
use base qw(WAP::wmls::SymbTab);
use constant UINT8_MAX => 255;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::SymbTab(@_);
bless $self, $class;
$self->{FunctionID} = 0;
return $self;
}
sub InsertLocal {
my $self = shift;
my ($symb, $type) = @_;
if ( $type eq 'PUBLIC_FUNC'
and length $symb > UINT8_MAX ) {
$self->{parser}->Error("Too long public function name - $symb.\n");
}
my $def = $self->{tab}{$symb};
if (defined $def) {
if ($def->{Type} ne 'UNDEF_FUNC') {
$self->{parser}->Error("Redefinition - $symb.\n");
}
else {
$def->{Type} = $type;
}
}
else {
$def = new WAP::wmls::defn($symb, $type);
$self->SUPER::Insert($symb, $def);
}
$def->{ID} = $self->{FunctionID} ++;
return $def;
}
sub LookupLocal {
my $self = shift;
my ($symb) = @_;
my $def = $self->{tab}{$symb};
unless (defined $def) {
$def = new WAP::wmls::defn($symb, 'UNDEF_FUNC');
$self->SUPER::Insert($symb, $def);
}
return $def;
}
sub LookupExternal {
my $self = shift;
my ($script, $func, $nbargs) = @_;
if (length $func > UINT8_MAX) {
$self->{parser}->Error("Too long external function name - $func.\n");
}
if ($nbargs > UINT8_MAX) {
$self->{parser}->Error("External function with too many parameter - $func.\n");
}
my $symb = $script . '#' . $func;
my $def = $self->{tab}{$symb};
if (defined $def) {
if ($nbargs != $def->{NumberOfArguments}) {
$self->{parser}->Error("Previous call with different argument number - $func.\n");
}
}
else {
$def = new WAP::wmls::defn($symb, 'EXTERN_FUNC');
$def->{FunctionName} = $func;
$def->{NumberOfArguments} = $nbargs;
$self->SUPER::Insert($symb, $def);
}
return $def;
}
sub LookupLibrary {
my $self = shift;
my ($library, $func, $nbargs) = @_;
my $symb = $library . '.' . $func;
my $def = $self->{tab}{$symb};
if (defined $def) {
if ($def->{NumberOfArguments} != $nbargs) {
$self->{parser}->Error("Wrong argument number for standard function - $func.\n");
}
return $def;
}
else {
$self->{parser}->Error("Library function unknown - $func.\n");
return;
}
}
sub InsertLibrary {
my $self = shift;
my ($symb, $libId, $id, $nbargs) = @_;
my $def = new WAP::wmls::defn($symb, 'STANDARD_FUNC');
$def->{LibraryID} = $libId;
$def->{ID} = $id;
$def->{NumberOfArguments} = $nbargs;
$self->SUPER::Insert($symb, $def);
return $def;
}
###############################################################################
package WAP::wmls::SymbTabUrl;
use base qw(WAP::wmls::SymbTab);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::SymbTab(@_);
bless $self, $class;
return $self;
}
sub Insert {
my $self = shift;
my ($symb) = @_;
my $def = new WAP::wmls::defn($symb);
$self->SUPER::Insert($symb, $def);
return $def;
}
sub Lookup {
my $self = shift;
my ($script) = @_;
if (exists $self->{tab}{$script}) {
my $def = $self->{tab}{$script};
$def->{NbUse} ++;
return $def;
}
else {
$self->{parser}->Error("ScriptName undefined - $script.\n");
return;
}
}
###############################################################################
package WAP::wmls::SymbTabLabel;
use constant UINT32_MAX => 4294967295;
use base qw(WAP::wmls::SymbTab);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = new WAP::wmls::SymbTab(@_);
$self->{idx} = 0;
bless $self, $class;
return $self;
}
sub Next {
my $self = shift;
my $symb = sprintf("L%d", $self->{idx}++);
my $def = new WAP::wmls::defn($symb);
$def->{Index} = UINT32_MAX;
$self->SUPER::Insert($symb, $def);
return $def;
}
1;