#!/usr/bin/perl
# Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
# e32toolp\e32util\h2inc.pl
# Convert structures in C++ include files to assembler format
# Syntax:
# perl h2inc.pl <input.h> <output.inc> <format>
# where <format>=arm or x86
#
#
# Version
my $MajorVersion = 1;
my $MinorVersion = 1;
my $PatchVersion = 0;
%basictypes = (
TInt8 => 1,
TUint8 => 1,
TInt16 => 2,
TUint16 => 2,
TInt32 => 4,
TUint32 => 4,
TInt => 4,
TUint => 4,
TInt64 => 8,
TUint64 => 8,
TLinAddr => 4,
TVersion => 4,
TPde => 4,
TPte => 4,
TProcessPriority => 4
);
if (scalar(@ARGV)!=3) {
die "H2INC format management tools V$MajorVersion.$MinorVersion.$PatchVersion\nperl h2inc.pl <input.h> <output.inc> <format>\n";
}
my ($infile, $outfile, $format) = @ARGV;
open IN, $infile or die "Can't open $infile for input\n";
my $in;
while (<IN>) {
$in.=$_;
}
close IN;
$format = uc($format);
$format_sub = undef();
$comment_sub = undef();
$end_sub = undef();
if ($format eq "ARMASM") {
$format_sub = \&armasm_format;
$comment_sub = \&armasm_comment;
$end_sub = \&armasm_end;
} elsif ($format eq "AS") {
$format_sub = \&as_format;
$comment_sub = \&as_comment;
$end_sub = \&as_end;
} elsif ($format eq "TASM") {
$format_sub = \&tasm_format;
$comment_sub = \&tasm_comment;
$end_sub = \&tasm_end;
} else {
die "Format $format unknown\nOnly ARMASM, AS or TASM supported\n";
}
# First remove any backslash-newline combinations
$in =~ s/\\\n//gms;
# Change escaped quotes to double quotes
$in =~ s/\\\"/\"\"/gms;
$in =~ s/\\\'/\'\'/gms;
# Remove any character constants
$in =~ s/\'(.?(${0})*?)\'//gms;
# Remove any string literals
$in =~ s/\"(.*?)\"//gms;
# Strip comments
$in =~ s/\/\*(.*?)\*\//\n/gms;
$in =~ s/\/\/(.*?)\n/\n/gms;
# Collapse whitespace into a single space or newline
$in =~ s/\t/\ /gms;
$in =~ s/\r/\ /gms;
$in =~ s/(\ )+/\ /gms;
$in =~ s/\n(\ )*/\n/gms;
$in =~ s/(\ )*\n/\n/gms;
# Tokenize on non-identifier characters
my @tokens0 = split(/(\W)/,$in);
my @tokens;
foreach $t (@tokens0) {
next if ($t eq " " or $t eq "");
push @tokens, $t;
}
my %macros;
my %filescope;
$filescope{file}=1;
$filescope{name}='*** FILE SCOPE ***';
my @ftypedefs;
$filescope{typedefs}=\@ftypedefs;
my $line=1;
parse_scope(\%filescope, \@tokens, \$line);
my @output;
push @output, &$comment_sub('*' x 80);
push @output, &$comment_sub($outfile);
push @output, &$comment_sub('*' x 80);
push @output, &$comment_sub("GENERATED FILE - DO NOT EDIT");
push @output, "";
output_scope(\%filescope, \@output);
push @output, &$end_sub();
push @output, "";
open OUT, ">$outfile" or die "Can't open $outfile for write\n";
print OUT join("\n", @output);
print OUT "\n\n";
close OUT;
sub get_token($$) {
my ($tokenlist,$line) = @_;
while (scalar(@$tokenlist)) {
my $t = shift @$tokenlist;
return $t if (!defined($t));
return $t if ($t !~ /^\s*$/);
++$$line;
}
}
sub skip_qualifiers($) {
my ($tokens) = @_;
my $f=0;
my %quals = (
EXPORT_C => 1,
IMPORT_C => 1,
inline => 1,
const => 0,
volatile => 0,
static => 0,
extern => 0,
LOCAL_C => 0,
LOCAL_D => 0,
GLDEF_C => 0,
GLREF_C => 0,
GLDEF_D => 0,
GLREF_D => 0
);
for (;;) {
my $t = $$tokens[0];
my $q = $quals{$t};
last unless (defined ($q));
$f |= $q;
shift @$tokens;
}
return $f;
}
sub parse_indirection($) {
my ($tokens) = @_;
my $level = 0;
for (;;) {
my $t = $$tokens[0];
if ($t eq '*') {
++$level;
shift @$tokens;
next;
}
last if ($t ne "const" and $t ne "volatile");
shift @$tokens;
}
return $level;
}
sub parse_scope($$$) {
my ($scope, $tokens, $line) = @_;
my $state = 0;
my %values;
my @classes;
my @enums;
my $curr_offset=0;
my $overall_align=0;
$scope->{values}=\%values;
$scope->{classes}=\@classes;
$scope->{enums}=\@enums;
while (scalar(@$tokens)) {
my $t = shift @$tokens;
if ($state>=-1 and $t eq "\n") {
++$$line;
$state=1;
next;
} elsif ($state==-1 and $t ne "\n") {
next;
} elsif ($state==-2 and $t ne ';') {
next;
}
if ($state>0 and $t eq '#') {
if ($scope->{scope}) {
warn "Preprocessor directive in class/struct at line $$line\n";
}
$t = shift @$tokens;
if ($t eq 'define') {
my $ident = shift @$tokens;
my $defn = shift @$tokens;
if ($defn ne '(') { # don't do macros with parameters
$macros{$ident} = $defn;
}
}
$state=-1; # skip to next line
next;
}
if ($t eq "struct" or $t eq "class") {
next if ($state==0);
$state=0;
my %cl;
$cl{specifier}=$t;
$cl{scope}=$scope;
my @members;
my @typedefs;
$cl{members}=\@members;
$cl{typedefs}=\@typedefs;
my $new_class = \%cl;
my $n = get_token($tokens,$line);
if ($n !~ /\w+/) {
die "Unnamed $t not supported at line $$line\n";
}
$new_class->{name}=$n;
my @class_match = grep {$_->{name} eq $n} @classes;
my $exists = scalar(@class_match);
my $b = get_token($tokens,$line);
if ($b eq ':') {
die "Inheritance not supported at line $$line\n";
} elsif ($b eq ';') {
# forward declaration
push @classes, $new_class unless ($exists);
next;
} elsif ($b ne '{') {
die "Syntax error at line $$line\n";
}
if ($exists) {
$new_class = $class_match[0];
if ($new_class->{complete}) {
die "Duplicate definition of $cl{specifier} $n\n";
}
}
push @classes, $new_class unless ($exists);
parse_scope($new_class, $tokens, $line);
next;
} elsif ($t eq "enum") {
$state=0;
my $n = get_token($tokens,$line);
my $name="";
if ($n =~ /\w+/) {
$name = $n;
$n = get_token($tokens,$line);
}
push @enums, $name;
if ($n ne '{') {
die "Syntax error at line $$line\n";
}
parse_enum($scope, $tokens, $line, $name);
next;
} elsif ($t eq '}') {
$state=0;
if ($scope->{scope}) {
$t = get_token($tokens,$line);
if ($t eq ';') {
$scope->{complete}=1;
last;
}
}
die "Syntax error at line $$line\n";
}
$state=0;
if ($scope->{scope}) {
if ($t eq "public" or $t eq "private" or $t eq "protected") {
if (shift (@$tokens) eq ':') {
next; # ignore access specifiers
}
die "Syntax error at line $$line\n";
}
}
unshift @$tokens, $t;
my @currdecl = parse_decl_def($scope, $tokens, $line);
if ($t eq 'static') {
next; # skip static members
}
my $typedef;
if ($t eq 'typedef') {
$typedef = 1;
$t = shift @currdecl;
$t = $currdecl[0];
} else {
$typedef = 0;
}
next if (scalar(@currdecl)==0);
if ($t eq "const") {
# check for constant declaration
my $ctype = lookup_type($scope, $currdecl[1]);
if ($ctype->{basic} and $currdecl[2]=~/^\w+$/ and $currdecl[3] eq '=') {
if ($typedef!=0) {
die "Syntax error at line $$line\n";
}
shift @currdecl;
shift @currdecl;
my $type = $ctype->{name};
my $name = shift @currdecl;
my $size = $ctype->{size};
shift @currdecl;
my $value = get_constant_expr($scope,\@currdecl,$line);
$values{$name} = {type=>$type, size=>$size, value=>$value};
next;
}
}
if (skip_qualifiers(\@currdecl)!=0 or ($scope->{file} and !$typedef)) {
next; # function declaration or stuff at file scope
}
my $type1 = shift @currdecl; # type, type pointed to or return type
if ($type1 !~ /^\w+$/) {
die "Syntax error at line $$line\n";
}
my $ind1 = parse_indirection(\@currdecl);
my $ident; # identifier being declared
my $size = -1;
my $array = -1;
my $align = 0;
my $alias;
my $category;
if ($currdecl[0] eq '(' and $currdecl[1] eq '*' and $currdecl[2]=~/^\w+$/) {
# function pointer
$ident = $currdecl[2];
$size = 4;
$category = 'fptr';
shift @currdecl;
shift @currdecl;
shift @currdecl;
} elsif ($currdecl[0]=~/^\w+$/) {
$ident = shift @currdecl;
if ($currdecl[0] ne '(') {
# not function declaration
if ($ind1>0) {
# pointer
$category = 'ptr';
$size = 4;
} else {
my $type2 = lookup_type($scope, $type1);
if (!defined($type2)) {
die "Unrecognised type $type1 at line $$line\n";
}
if ($type2->{basic}) {
$alias = $type2->{name};
$size = $type2->{size};
$category = 'basic';
} elsif ($type2->{enum}) {
$alias = $type2->{name};
$category = 'enum';
$size = 4;
} elsif ($type2->{class}) {
$alias = $type2->{name};
$size = $type2->{class}->{size};
$category = 'class';
$align = $type2->{class}->{align};
} elsif ($type->{ptr}) {
$size = 4;
$category = 'ptr';
$align = 4;
} elsif ($type->{fptr}) {
$size = 4;
$category = 'ptr';
$align = 4;
}
}
}
}
if ($size>0) {
# data member declared
# check for array
if ($currdecl[0] eq '[') {
shift @currdecl;
$array = get_constant_expr($scope, \@currdecl, $line);
if ($array<=0) {
die "Bad array size at line $$line\n";
}
if ($currdecl[0] ne ']') {
die "Syntax error at line $$line\n";
}
}
my $members = $scope->{members};
my $typedefs = $scope->{typedefs};
if ($align==0) {
$align = $size;
}
my $am = $align-1;
unless ($typedef) {
my $al = $curr_offset & $am;
if ($align==8 and $al!=0) {
die "Bad alignment of 64-bit data $ident at line $$line\n";
}
$curr_offset += ($align-$al) if ($al!=0);
}
if ($array>0) {
$size = ($size + $am) &~ $am;
if ($typedef) {
push @$typedefs, {name=>$ident, category=>$category, alias=>$alias, size=>$size*$array, spacing=>$size, array=>$array};
} else {
push @$members, {name=>$ident, size=>$size*$array, offset=>$curr_offset, spacing=>$size};
}
$size *= $array;
} else {
if ($typedef) {
push @$typedefs, {name=>$ident, category=>$category, alias=>$alias, size=>$size};
} else {
push @$members, {name=>$ident, size=>$size, offset=>$curr_offset};
}
}
unless ($typedef) {
$curr_offset += $size;
if ($align > $overall_align) {
$overall_align = $align;
}
}
}
}
if ($scope->{scope}) {
if ($state==-2) {
die "Missing ; at end of file\n";
}
if (!$scope->{complete}) {
die "Unexpected end of file at line $$line\n";
}
my $total_size = ($curr_offset + $overall_align - 1) &~ ($overall_align - 1);
$scope->{size} = $total_size;
$scope->{align} = $overall_align;
}
}
sub get_operand($$$) {
my ($scope,$tokens,$line) = @_;
my $t = get_token($tokens,$line);
if ($t eq '-') {
my $x = get_operand($scope,$tokens,$line);
return -$x;
} elsif ($t eq '+') {
my $x = get_operand($scope,$tokens,$line);
return $x;
} elsif ($t eq '~') {
my $x = get_operand($scope,$tokens,$line);
return ~$x;
} elsif ($t eq '!') {
my $x = get_operand($scope,$tokens,$line);
return $x ? 0 : 1;
} elsif ($t eq '(') {
my $x = get_constant_expr($scope,$tokens,$line);
my $t = get_token($tokens,$line);
if ($t ne ')') {
die "Missing ) at line $$line\n";
}
return $x;
} elsif ($t eq "sizeof") {
my $ident = get_token($tokens,$line);
if ($ident eq '(') {
$ident = get_token($tokens,$line);
my $cb = get_token($tokens,$line);
if ($cb ne ')') {
die "Bad sizeof() syntax at line $$line\n";
}
}
$ident = look_through_macros($ident);
if ($ident !~ /^\w+$/) {
die "Bad sizeof() syntax at line $$line\n";
}
my $type = lookup_type($scope, $ident);
if (!defined $type) {
die "Unrecognised type $ident at line $$line\n";
}
if ($type->{basic}) {
return $type->{size};
} elsif ($type->{enum}) {
return 4;
} elsif ($type->{ptr}) {
return 4;
} elsif ($type->{fptr}) {
return 4;
}
my $al = $type->{class}->{align};
my $sz = $type->{class}->{size};
return ($sz+$al-1)&~($al-1);
}
$t = look_through_macros($t);
if ($t =~ /^0x[0-9a-f]+/i) {
return oct($t);
} elsif ($t =~ /^\d/) {
return $t;
} elsif ($t =~ /^\w+$/) {
my $x = lookup_value($scope,$t);
die "Unrecognised identifier '$t' at line $$line\n" unless defined($x);
return $x;
} else {
die "Syntax error at line $$line\n";
}
}
sub look_through_macros($) {
my ($ident) = @_;
while ($ident and $macros{$ident}) {
$ident = $macros{$ident};
}
return $ident;
}
sub lookup_value($$) {
my ($scope,$ident) = @_;
while ($scope) {
my $vl = $scope->{values};
if (defined($vl->{$ident})) {
return $vl->{$ident}->{value};
}
$scope = $scope->{scope};
}
return undef();
}
sub lookup_type($$) {
my ($scope,$ident) = @_;
if ($basictypes{$ident}) {
return {scope=>$scope, basic=>1, name=>$ident, size=>$basictypes{$ident} };
}
while ($scope) {
if ($basictypes{$ident}) {
return {scope=>$scope, basic=>1, name=>$ident, size=>$basictypes{$ident} };
}
my $el = $scope->{enums};
my $cl = $scope->{classes};
my $td = $scope->{typedefs};
if (grep {$_ eq $ident} @$el) {
return {scope=>$scope, enum=>1, name=>$ident, size=>4 };
}
my @match_class = (grep {$_->{name} eq $ident} @$cl);
if (scalar(@match_class)) {
return {scope=>$scope, class=>$match_class[0]};
}
my @match_td = (grep {$_->{name} eq $ident} @$td);
if (scalar(@match_td)) {
my $tdr = $match_td[0];
my $cat = $tdr->{category};
if ($cat eq 'basic' or $cat eq 'enum' or $cat eq 'class') {
$ident = $tdr->{alias};
next;
} else {
return { scope=>$scope, $cat=>1, $size=>$tdr->{size} };
}
}
$scope = $scope->{scope};
}
return undef();
}
sub get_mult_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_operand($scope,$tokens,$line);
my $t;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '*') {
my $y = get_operand($scope,$tokens,$line);
$x = $x * $y;
} elsif ($t eq '/') {
my $y = get_operand($scope,$tokens,$line);
$x = int($x / $y);
} elsif ($t eq '%') {
my $y = get_operand($scope,$tokens,$line);
$x = int($x % $y);
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_add_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_mult_expr($scope,$tokens,$line);
my $t;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '+') {
my $y = get_mult_expr($scope,$tokens,$line);
$x = $x + $y;
} elsif ($t eq '-') {
my $y = get_mult_expr($scope,$tokens,$line);
$x = $x - $y;
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_shift_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_add_expr($scope,$tokens,$line);
my $t, $t2;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '<' or $t eq '>') {
$t2 = get_token($tokens,$line);
if ($t2 ne $t) {
unshift @$tokens, $t2;
last;
}
}
if ($t eq '<') {
my $y = get_add_expr($scope,$tokens,$line);
$x = $x << $y;
} elsif ($t eq '>') {
my $y = get_add_expr($scope,$tokens,$line);
$x = $x >> $y;
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_and_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_shift_expr($scope,$tokens,$line);
my $t;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '&') {
my $y = get_shift_expr($scope,$tokens,$line);
$x = $x & $y;
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_xor_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_and_expr($scope,$tokens,$line);
my $t;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '^') {
my $y = get_and_expr($scope,$tokens,$line);
$x = $x ^ $y;
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_ior_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_xor_expr($scope,$tokens,$line);
my $t;
for (;;) {
$t = get_token($tokens,$line);
if ($t eq '|') {
my $y = get_xor_expr($scope,$tokens,$line);
$x = $x | $y;
} else {
last;
}
}
unshift @$tokens, $t;
return $x;
}
sub get_constant_expr($$$) {
my ($scope,$tokens,$line) = @_;
my $x = get_ior_expr($scope,$tokens,$line);
return $x;
}
sub parse_enum($$$$) {
my ($scope,$tokens,$line,$enum_name) = @_;
my $vl = $scope->{values};
my $x = 0;
for (;;) {
my $t = get_token($tokens,$line);
last if ($t eq '}');
if (!defined($t)) {
die "Unexpected end of file at line $$line\n";
}
if ($t !~ /^\w+$/) {
die "Syntax error at line $$line\n";
}
if (defined($vl->{$t})) {
die "Duplicate identifier at line $$line\n";
}
my $t2 = get_token($tokens,$line);
if ($t2 eq ',') {
$vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
++$x;
} elsif ($t2 eq '}') {
$vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
++$x;
last;
} elsif ($t2 eq '=') {
$x = get_constant_expr($scope, $tokens, $line);
$vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
++$x;
$t2 = get_token($tokens,$line);
last if ($t2 eq '}');
next if ($t2 eq ',');
die "Syntax error at line $$line\n";
} else {
unshift @$tokens, $t2;
}
}
my $t = get_token($tokens,$line);
if ($t ne ';') {
die "Missing ; at line $$line\n";
}
}
sub parse_decl_def($$$) {
my ($scope,$tokens,$line) = @_;
my $level=0;
my @decl;
while ( scalar(@$tokens) ) {
my $t = get_token($tokens, $line);
if ($t eq ';' and $level==0) {
return @decl;
}
push @decl, $t;
if ($t eq '{') {
++$level;
}
if ($t eq '}') {
if ($level==0) {
die "Syntax error at line $$line\n";
}
if (--$level==0) {
return (); # end of function definition reached
}
}
}
die "Unexpected end of file at line $$line\n";
}
sub dump_scope($) {
my ($scope) = @_;
my $el = $scope->{enums};
my $cl = $scope->{classes};
my $vl = $scope->{values};
print "SCOPE: $scope->{name}\n";
if (scalar(@$el)) {
print "\tenums:\n";
foreach (@$el) {
print "\t\t$_\n";
}
}
if (scalar(keys(%$vl))) {
print "\tvalues:\n";
foreach $vname (keys(%$vl)) {
my $v = $vl->{$vname};
my $x = $v->{value};
my $t = $v->{type};
my $sz = $v->{size};
if ($v->{enum}) {
print "\t\t$vname\=$x (enum $t) size=$sz\n";
} else {
print "\t\t$vname\=$x (type $t) size=$sz\n";
}
}
}
if ($scope->{scope}) {
my $members = $scope->{members};
foreach (@$members) {
my $n = $_->{name};
my $sz = $_->{size};
my $off = $_->{offset};
my $spc = $_->{spacing};
if (defined $spc) {
print "\t$n\[\]\: spacing $spc size $sz offset $off\n";
} else {
print "\t$n\: size $sz offset $off\n";
}
}
print "\tOverall size : $scope->{size}\n";
print "\tOverall align: $scope->{align}\n";
}
foreach $s (@$cl) {
dump_scope($s);
}
}
sub output_scope($$) {
my ($scope, $out) = @_;
my $el = $scope->{enums};
my $cl = $scope->{classes};
my $vl = $scope->{values};
my $sn = scope_full_name($scope);
my $sp = ($scope->{file}) ? "" : $sn."_";
if ($scope->{file}) {
push @$out, "";
push @$out, &$comment_sub("FILE SCOPE");
push @$out, "";
} else {
push @$out, "";
push @$out, &$comment_sub($scope->{specifier}." ".$scope->{name});
push @$out, "";
}
if (scalar(keys(%$vl))) {
foreach $vname (keys(%$vl)) {
my $v = $vl->{$vname};
my $x = $v->{value};
my $t = $v->{type};
my $sz = $v->{size};
push @$out, &$format_sub($sp.$vname, $x);
}
}
if ($scope->{scope}) {
my $members = $scope->{members};
foreach (@$members) {
my $n = $_->{name};
my $sz = $_->{size};
my $off = $_->{offset};
my $spc = $_->{spacing};
push @$out, &$format_sub($sp.$n, $off);
if (defined $spc) {
push @$out, &$format_sub($sp.$n."_spc", $spc);
}
}
push @$out, &$format_sub($sp."sz", $scope->{size});
}
foreach $s (@$cl) {
if ($s->{complete}) {
output_scope($s, $out);
}
}
}
sub scope_full_name($) {
my ($scope) = @_;
if ($scope->{file}) {
return "";
}
my $parent = $scope->{scope};
if ($parent->{file}) {
return $scope->{name};
}
return scope_full_name($parent)."_".$scope->{name};
}
sub pad($$) {
my ($lineref, $n) = @_;
my $l = length ($$lineref);
if ($l < $n) {
$$lineref .= ' 'x($n-$l);
}
}
#
# Subroutines for ARMASM compatible output
#
sub armasm_format($$;$) {
my ($name, $value, $comment) = @_;
my $r = "$name ";
pad(\$r, 40);
$r .= sprintf("EQU 0x%08x", $value & 0xFFFFFFFF);
if ($comment and $comment!~/^\s*$/) {
$r .= " ";
pad(\$r, 60);
$r .= "; $comment";
}
return $r;
}
sub armasm_comment($) {
my ($comment) = @_;
return "; $comment";
}
sub armasm_end() {
return "\n\tEND\n";
}
#
# Subroutines for GNU AS compatible output
#
sub as_format($$;$) {
my ($name, $value, $comment) = @_;
my $r = " .equ $name, ";
pad(\$r, 50);
$r .= sprintf("0x%08x", $value & 0xFFFFFFFF);
if ($comment and $comment!~/^\s*$/) {
$r .= " ";
pad(\$r, 65);
$r .= "/* $comment */";
}
return $r;
}
sub as_comment($) {
my ($comment) = @_;
if (length ($comment) > 0) {
return "/* $comment */";
} else {
return "";
}
}
sub as_end() {
return "";
}
#
# Subroutines for Turbo Assembler compatible output
#
sub tasm_format($$;$) {
my ($name, $value, $comment) = @_;
my $r = "$name ";
pad(\$r, 40);
$r .= sprintf("EQU 0%08xh", $value & 0xFFFFFFFF);
if ($comment and $comment!~/^\s*$/) {
$r .= " ";
pad(\$r, 60);
$r .= "; $comment";
}
return $r;
}
sub tasm_comment($) {
my ($comment) = @_;
return "; $comment";
}
sub tasm_end() {
return "";
}