Commit 0c9a59a3 authored by Ghislain MARY's avatar Ghislain MARY

Install gas-preprocessor.pl automatically + Disable NLS on Android and iOS so...

Install gas-preprocessor.pl automatically + Disable NLS on Android and iOS so that intltoolize dependency is not needed.
parent cbf3897d
......@@ -67,6 +67,10 @@ else()
include(${LINPHONE_BUILDER_CONFIG_FILE})
# Check for build tools and show an error if one of them is not present
include(cmake/CheckBuildTools.cmake)
# Apply build flags
linphone_builder_apply_flags()
......
......@@ -43,10 +43,6 @@ else()
endif()
# Check for build tools and show an error if one of them is not present
include(cmake/CheckBuildTools.cmake)
set(LINPHONE_BUILDER_EP_VARS)
set(LINPHONE_BUILDER_INCLUDED_BUILDERS)
set(LINPHONE_BUILDER_INCLUDED_BUILDERS_TO_EXCLUDE)
......
......@@ -52,9 +52,10 @@ if(MSVC AND NOT WINDOWS_UNIVERSAL)
execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${MINGWEX_LIBRARY}" "${CMAKE_INSTALL_PREFIX}/lib/mingwex.lib")
endif()
set(CMAKE_PROGRAM_PATH "${CMAKE_BINARY_DIR}/programs")
file(MAKE_DIRECTORY ${CMAKE_PROGRAM_PATH})
file(COPY "${CMAKE_CURRENT_LIST_DIR}/../scripts/gas-preprocessor.pl" DESTINATION "${CMAKE_PROGRAM_PATH}")
if(WIN32)
set(CMAKE_PROGRAM_PATH "${CMAKE_BINARY_DIR}/programs")
file(MAKE_DIRECTORY ${CMAKE_PROGRAM_PATH})
if(NOT EXISTS "${CMAKE_BINARY_DIR}/linphone_builder_windows_tools.zip")
message(STATUS "Installing windows tools")
file(DOWNLOAD https://www.linphone.org/files/linphone_builder_windows_tools.zip "${CMAKE_BINARY_DIR}/linphone_builder_windows_tools.zip")
......@@ -142,6 +143,7 @@ if(NOT WINDOWS_UNIVERSAL)
message(FATAL_ERROR "Could not find the pkg-config program.")
endif()
if(ENABLE_NLS)
find_program(INTLTOOLIZE_PROGRAM
NAMES intltoolize
HINTS "C:/MinGW/msys/1.0/bin"
......@@ -183,6 +185,7 @@ if(NOT WINDOWS_UNIVERSAL)
if(NOT INTLTOOLIZE_PROGRAM AND NOT MSVC)
message(FATAL_ERROR "Could not find the intltoolize program.")
endif()
endif()
endif()
if(MSVC AND NOT WINDOWS_UNIVERSAL)
......
......@@ -28,6 +28,7 @@ CXXFLAGS="@ep_cxxflags@"
OBJCFLAGS="@ep_objcflags@"
LDFLAGS="@ep_ldflags@"
export PATH="@CMAKE_PROGRAM_PATH@:$PATH"
export PKG_CONFIG="@LINPHONE_BUILDER_PKG_CONFIG@"
export PKG_CONFIG_PATH="@LINPHONE_BUILDER_PKG_CONFIG_PATH@"
export PKG_CONFIG_LIBDIR="@LINPHONE_BUILDER_PKG_CONFIG_LIBDIR@"
......
......@@ -28,6 +28,7 @@ CXXFLAGS="@ep_cxxflags@"
OBJCFLAGS="@ep_objcflags@"
LDFLAGS="@ep_ldflags@"
export PATH="@CMAKE_PROGRAM_PATH@:$PATH"
export PKG_CONFIG="@LINPHONE_BUILDER_PKG_CONFIG@"
export PKG_CONFIG_PATH="@LINPHONE_BUILDER_PKG_CONFIG_PATH@"
export PKG_CONFIG_LIBDIR="@LINPHONE_BUILDER_PKG_CONFIG_LIBDIR@"
......
......@@ -28,6 +28,7 @@ CXXFLAGS="@ep_cxxflags@"
OBJCFLAGS="@ep_objcflags@"
LDFLAGS="@ep_ldflags@"
export PATH="@CMAKE_PROGRAM_PATH@:$PATH"
export PKG_CONFIG="@LINPHONE_BUILDER_PKG_CONFIG@"
export PKG_CONFIG_PATH="@LINPHONE_BUILDER_PKG_CONFIG_PATH@"
export PKG_CONFIG_LIBDIR="@LINPHONE_BUILDER_PKG_CONFIG_LIBDIR@"
......
......@@ -39,6 +39,7 @@ set(DEFAULT_VALUE_ENABLE_VIDEO ON)
set(DEFAULT_VALUE_ENABLE_VPX ON)
set(DEFAULT_VALUE_ENABLE_WEBRTC_AEC ON)
set(DEFAULT_VALUE_ENABLE_ZRTP ON)
set(ENABLE_NLS NO CACHE BOOL "" FORCE)
set(DEFAULT_VALUE_CMAKE_LINKING_TYPE "-DENABLE_STATIC=YES" "-DENABLE_SHARED=NO")
set(DEFAULT_VALUE_CMAKE_PLUGIN_LINKING_TYPE "-DENABLE_STATIC=NO" "-DENABLE_SHARED=YES")
......@@ -89,7 +90,6 @@ list(APPEND EP_linphone_CMAKE_OPTIONS
"-DENABLE_MSG_STORAGE=YES"
"-DENABLE_DOC=NO"
"-DENABLE_UNIT_TESTS=YES"
"-DENABLE_NLS=NO"
)
set(EP_linphone_LINKING_TYPE "-DENABLE_STATIC=NO" "-DENABLE_SHARED=YES")
......
......@@ -37,6 +37,7 @@ set(DEFAULT_VALUE_ENABLE_UNIT_TESTS ON)
set(DEFAULT_VALUE_ENABLE_VIDEO ON)
set(DEFAULT_VALUE_ENABLE_VPX ON)
set(DEFAULT_VALUE_ENABLE_ZRTP ON)
set(ENABLE_NLS NO CACHE BOOL "" FORCE)
set(DEFAULT_VALUE_CMAKE_LINKING_TYPE "-DENABLE_STATIC=YES" "-DENABLE_SHARED=NO")
......
#!/usr/bin/env perl
# by David Conrad
# This code is licensed under GPLv2 or later; go to gnu.org to read it
# (not that it much matters for an asm preprocessor)
# usage: set your assembler to be something like "perl gas-preprocessor.pl gcc"
use strict;
# Apple's gas is ancient and doesn't support modern preprocessing features like
# .rept and has ugly macro syntax, among other things. Thus, this script
# implements the subset of the gas preprocessor used by x264 and ffmpeg
# that isn't supported by Apple's gas.
my %canonical_arch = ("aarch64" => "aarch64", "arm64" => "aarch64",
"arm" => "arm",
"powerpc" => "powerpc", "ppc" => "powerpc");
my %comments = ("aarch64" => '//',
"arm" => '@',
"powerpc" => '#');
my @gcc_cmd;
my @preprocess_c_cmd;
my $comm;
my $arch;
my $as_type = "apple-gas";
my $fix_unreq = $^O eq "darwin";
my $force_thumb = 0;
my $arm_cond_codes = "eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo";
my $usage_str = "
$0\n
Gas-preprocessor.pl converts assembler files using modern GNU as syntax for
Apple's ancient gas version or clang's incompatible integrated assembler. The
conversion is regularly tested for Libav, x264 and vlc. Other projects might
use different features which are not correctly handled.
Options for this program needs to be separated with ' -- ' from the assembler
command. Following options are currently supported:
-help - this usage text
-arch - target architecture
-as-type - one value out of {{,apple-}{gas,clang},armasm}
-fix-unreq
-no-fix-unreq
-force-thumb - assemble as thumb regardless of the input source
(note, this is incomplete and only works for sources
it explicitly was tested with)
";
sub usage() {
print $usage_str;
}
while (@ARGV) {
my $opt = shift;
if ($opt =~ /^-(no-)?fix-unreq$/) {
$fix_unreq = $1 ne "no-";
} elsif ($opt eq "-force-thumb") {
$force_thumb = 1;
} elsif ($opt eq "-arch") {
$arch = shift;
die "unknown arch: '$arch'\n" if not exists $canonical_arch{$arch};
} elsif ($opt eq "-as-type") {
$as_type = shift;
die "unknown as type: '$as_type'\n" if $as_type !~ /^((apple-)?(gas|clang)|armasm)$/;
} elsif ($opt eq "-help") {
usage();
exit 0;
} elsif ($opt eq "--" ) {
@gcc_cmd = @ARGV;
} elsif ($opt =~ /^-/) {
die "option '$opt' is not known. See '$0 -help' for usage information\n";
} else {
push @gcc_cmd, $opt, @ARGV;
}
last if (@gcc_cmd);
}
if (grep /\.c$/, @gcc_cmd) {
# C file (inline asm?) - compile
@preprocess_c_cmd = (@gcc_cmd, "-S");
} elsif (grep /\.[sS]$/, @gcc_cmd) {
# asm file, just do C preprocessor
@preprocess_c_cmd = (@gcc_cmd, "-E");
} elsif (grep /-(v|h|-version|dumpversion)/, @gcc_cmd) {
# pass -v/--version along, used during probing. Matching '-v' might have
# uninteded results but it doesn't matter much if gas-preprocessor or
# the compiler fails.
exec(@gcc_cmd);
} else {
die "Unrecognized input filetype";
}
if ($as_type eq "armasm") {
$preprocess_c_cmd[0] = "cpp";
push(@preprocess_c_cmd, "-U__ELF__");
push(@preprocess_c_cmd, "-U__MACH__");
@preprocess_c_cmd = grep ! /^-nologo$/, @preprocess_c_cmd;
# Remove -ignore XX parameter pairs from preprocess_c_cmd
my $index = 1;
while ($index < $#preprocess_c_cmd) {
if ($preprocess_c_cmd[$index] eq "-ignore" and $index + 1 < $#preprocess_c_cmd) {
splice(@preprocess_c_cmd, $index, 2);
next;
}
$index++;
}
if (grep /^-MM$/, @preprocess_c_cmd) {
system(@preprocess_c_cmd) == 0 or die "Error running preprocessor";
exit 0;
}
}
# if compiling, avoid creating an output file named '-.o'
if ((grep /^-c$/, @gcc_cmd) && !(grep /^-o/, @gcc_cmd)) {
foreach my $i (@gcc_cmd) {
if ($i =~ /\.[csS]$/) {
my $outputfile = $i;
$outputfile =~ s/\.[csS]$/.o/;
push(@gcc_cmd, "-o");
push(@gcc_cmd, $outputfile);
last;
}
}
}
# replace only the '-o' argument with '-', avoids rewriting the make dependency
# target specified with -MT to '-'
my $index = 1;
while ($index < $#preprocess_c_cmd) {
if ($preprocess_c_cmd[$index] eq "-o") {
$index++;
$preprocess_c_cmd[$index] = "-";
}
$index++;
}
my $tempfile;
if ($as_type ne "armasm") {
@gcc_cmd = map { /\.[csS]$/ ? qw(-x assembler -) : $_ } @gcc_cmd;
} else {
@preprocess_c_cmd = grep ! /^-c$/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-m/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-G/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-W/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-Z/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-fp/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-EHsc$/, @preprocess_c_cmd;
@preprocess_c_cmd = grep ! /^-O/, @preprocess_c_cmd;
@gcc_cmd = grep ! /^-G/, @gcc_cmd;
@gcc_cmd = grep ! /^-W/, @gcc_cmd;
@gcc_cmd = grep ! /^-Z/, @gcc_cmd;
@gcc_cmd = grep ! /^-fp/, @gcc_cmd;
@gcc_cmd = grep ! /^-EHsc$/, @gcc_cmd;
@gcc_cmd = grep ! /^-O/, @gcc_cmd;
my @outfiles = grep /\.(o|obj)$/, @gcc_cmd;
$tempfile = $outfiles[0].".asm";
# Remove most parameters from gcc_cmd, which actually is the armasm command,
# which doesn't support any of the common compiler/preprocessor options.
@gcc_cmd = grep ! /^-D/, @gcc_cmd;
@gcc_cmd = grep ! /^-U/, @gcc_cmd;
@gcc_cmd = grep ! /^-m/, @gcc_cmd;
@gcc_cmd = grep ! /^-M/, @gcc_cmd;
@gcc_cmd = grep ! /^-c$/, @gcc_cmd;
@gcc_cmd = grep ! /^-I/, @gcc_cmd;
@gcc_cmd = map { /\.S$/ ? $tempfile : $_ } @gcc_cmd;
}
# detect architecture from gcc binary name
if (!$arch) {
if ($gcc_cmd[0] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
$arch = $1;
} else {
# look for -arch flag
foreach my $i (1 .. $#gcc_cmd-1) {
if ($gcc_cmd[$i] eq "-arch" and
$gcc_cmd[$i+1] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
$arch = $1;
}
}
}
}
# assume we're not cross-compiling if no -arch or the binary doesn't have the arch name
$arch = qx/arch/ if (!$arch);
die "Unknown target architecture '$arch'" if not exists $canonical_arch{$arch};
$arch = $canonical_arch{$arch};
$comm = $comments{$arch};
my $inputcomm = $comm;
$comm = ";" if $as_type =~ /armasm/;
my %ppc_spr = (ctr => 9,
vrsave => 256);
open(INPUT, "-|", @preprocess_c_cmd) || die "Error running preprocessor";
if ($ENV{GASPP_DEBUG}) {
open(ASMFILE, ">&STDOUT");
} else {
if ($as_type ne "armasm") {
open(ASMFILE, "|-", @gcc_cmd) or die "Error running assembler";
} else {
open(ASMFILE, ">", $tempfile);
}
}
my $current_macro = '';
my $macro_level = 0;
my $rept_level = 0;
my %macro_lines;
my %macro_args;
my %macro_args_default;
my $macro_count = 0;
my $altmacro = 0;
my $in_irp = 0;
my $num_repts;
my @rept_lines;
my @irp_args;
my $irp_param;
my @ifstack;
my %symbols;
my @sections;
my %literal_labels; # for ldr <reg>, =<expr>
my $literal_num = 0;
my $literal_expr = ".word";
$literal_expr = ".quad" if $arch eq "aarch64";
my $thumb = 0;
my %thumb_labels;
my %call_targets;
my %mov32_targets;
my %neon_alias_reg;
my %neon_alias_type;
my $temp_label_next = 0;
my %last_temp_labels;
my %next_temp_labels;
my %labels_seen;
my %aarch64_req_alias;
if ($force_thumb) {
parse_line(".thumb\n");
}
# pass 1: parse .macro
# note that the handling of arguments is probably overly permissive vs. gas
# but it should be the same for valid cases
while (<INPUT>) {
# remove lines starting with '#', preprocessing is done, '#' at start of
# the line indicates a comment for all supported archs (aarch64, arm, ppc
# and x86). Also strips line number comments but since they are off anyway
# it is no loss.
s/^#.*$//;
# remove all comments (to avoid interfering with evaluating directives)
s/(?<!\\)$inputcomm.*//x;
# Strip out windows linefeeds
s/\r$//;
foreach my $subline (split(";", $_)) {
# Add newlines at the end of lines that don't already have one
chomp $subline;
$subline .= "\n";
parse_line($subline);
}
}
sub eval_expr {
my $expr = $_[0];
while ($expr =~ /([A-Za-z._][A-Za-z0-9._]*)/g) {
my $sym = $1;
$expr =~ s/$sym/($symbols{$sym})/ if defined $symbols{$sym};
}
eval $expr;
}
sub handle_if {
my $line = $_[0];
# handle .if directives; apple's assembler doesn't support important non-basic ones
# evaluating them is also needed to handle recursive macros
if ($line =~ /\.if(n?)([a-z]*)\s+(.*)/) {
my $result = $1 eq "n";
my $type = $2;
my $expr = $3;
if ($type eq "b") {
$expr =~ s/\s//g;
$result ^= $expr eq "";
} elsif ($type eq "c") {
if ($expr =~ /(.*)\s*,\s*(.*)/) {
$result ^= $1 eq $2;
} else {
die "argument to .ifc not recognized";
}
} elsif ($type eq "") {
$result ^= eval_expr($expr) != 0;
} elsif ($type eq "eq") {
$result = eval_expr($expr) == 0;
} elsif ($type eq "lt") {
$result = eval_expr($expr) < 0;
} else {
chomp($line);
die "unhandled .if varient. \"$line\"";
}
push (@ifstack, $result);
return 1;
} else {
return 0;
}
}
sub parse_if_line {
my $line = $_[0];
# evaluate .if blocks
if (scalar(@ifstack)) {
# Don't evaluate any new if statements if we're within
# a repetition or macro - they will be evaluated once
# the repetition is unrolled or the macro is expanded.
if (scalar(@rept_lines) == 0 and $macro_level == 0) {
if ($line =~ /\.endif/) {
pop(@ifstack);
return 1;
} elsif ($line =~ /\.elseif\s+(.*)/) {
if ($ifstack[-1] == 0) {
$ifstack[-1] = !!eval_expr($1);
} elsif ($ifstack[-1] > 0) {
$ifstack[-1] = -$ifstack[-1];
}
return 1;
} elsif ($line =~ /\.else/) {
$ifstack[-1] = !$ifstack[-1];
return 1;
} elsif (handle_if($line)) {
return 1;
}
}
# discard lines in false .if blocks
foreach my $i (0 .. $#ifstack) {
if ($ifstack[$i] <= 0) {
return 1;
}
}
}
return 0;
}
sub parse_line {
my $line = $_[0];
return if (parse_if_line($line));
if (scalar(@rept_lines) == 0) {
if (/\.macro/) {
$macro_level++;
if ($macro_level > 1 && !$current_macro) {
die "nested macros but we don't have master macro";
}
} elsif (/\.endm/) {
$macro_level--;
if ($macro_level < 0) {
die "unmatched .endm";
} elsif ($macro_level == 0) {
$current_macro = '';
return;
}
}
}
if ($macro_level == 0) {
if ($line =~ /\.(rept|irp)/) {
$rept_level++;
} elsif ($line =~ /.endr/) {
$rept_level--;
}
}
if ($macro_level > 1) {
push(@{$macro_lines{$current_macro}}, $line);
} elsif (scalar(@rept_lines) and $rept_level >= 1) {
push(@rept_lines, $line);
} elsif ($macro_level == 0) {
expand_macros($line);
} else {
if ($line =~ /\.macro\s+([\d\w\.]+)\s*,?\s*(.*)/) {
$current_macro = $1;
# commas in the argument list are optional, so only use whitespace as the separator
my $arglist = $2;
$arglist =~ s/,/ /g;
my @args = split(/\s+/, $arglist);
foreach my $i (0 .. $#args) {
my @argpair = split(/=/, $args[$i]);
$macro_args{$current_macro}[$i] = $argpair[0];
$argpair[0] =~ s/:vararg$//;
$macro_args_default{$current_macro}{$argpair[0]} = $argpair[1];
}
# ensure %macro_lines has the macro name added as a key
$macro_lines{$current_macro} = [];
} elsif ($current_macro) {
push(@{$macro_lines{$current_macro}}, $line);
} else {
die "macro level without a macro name";
}
}
}
sub handle_set {
my $line = $_[0];
if ($line =~ /\.(?:set|equ)\s+(\S*)\s*,\s*(.*)/) {
$symbols{$1} = eval_expr($2);
return 1;
}
return 0;
}
sub expand_macros {
my $line = $_[0];
# handle .if directives; apple's assembler doesn't support important non-basic ones
# evaluating them is also needed to handle recursive macros
if (handle_if($line)) {
return;
}
if (/\.purgem\s+([\d\w\.]+)/) {
delete $macro_lines{$1};
delete $macro_args{$1};
delete $macro_args_default{$1};
return;
}
if ($line =~ /\.altmacro/) {
$altmacro = 1;
return;
}
if ($line =~ /\.noaltmacro/) {
$altmacro = 0;
return;
}
$line =~ s/\%([^,]*)/eval_expr($1)/eg if $altmacro;
# Strip out the .set lines from the armasm output
return if (handle_set($line) and $as_type eq "armasm");
if ($line =~ /\.rept\s+(.*)/) {
$num_repts = $1;
@rept_lines = ("\n");
# handle the possibility of repeating another directive on the same line
# .endr on the same line is not valid, I don't know if a non-directive is
if ($num_repts =~ s/(\.\w+.*)//) {
push(@rept_lines, "$1\n");
}
$num_repts = eval_expr($num_repts);
} elsif ($line =~ /\.irp\s+([\d\w\.]+)\s*(.*)/) {
$in_irp = 1;
$num_repts = 1;
@rept_lines = ("\n");
$irp_param = $1;
# only use whitespace as the separator
my $irp_arglist = $2;
$irp_arglist =~ s/,/ /g;
$irp_arglist =~ s/^\s+//;
@irp_args = split(/\s+/, $irp_arglist);
} elsif ($line =~ /\.irpc\s+([\d\w\.]+)\s*(.*)/) {
$in_irp = 1;
$num_repts = 1;
@rept_lines = ("\n");
$irp_param = $1;
my $irp_arglist = $2;
$irp_arglist =~ s/,/ /g;
$irp_arglist =~ s/^\s+//;
@irp_args = split(//, $irp_arglist);
} elsif ($line =~ /\.endr/) {
my @prev_rept_lines = @rept_lines;
my $prev_in_irp = $in_irp;
my @prev_irp_args = @irp_args;
my $prev_irp_param = $irp_param;
my $prev_num_repts = $num_repts;
@rept_lines = ();
$in_irp = 0;
@irp_args = '';
if ($prev_in_irp != 0) {
foreach my $i (@prev_irp_args) {
foreach my $origline (@prev_rept_lines) {
my $line = $origline;
$line =~ s/\\$prev_irp_param/$i/g;
$line =~ s/\\\(\)//g; # remove \()
parse_line($line);
}
}
} else {
for (1 .. $prev_num_repts) {
foreach my $origline (@prev_rept_lines) {
my $line = $origline;
parse_line($line);
}
}
}
} elsif ($line =~ /(\S+:|)\s*([\w\d\.]+)\s*(.*)/ && exists $macro_lines{$2}) {
handle_serialized_line($1);
my $macro = $2;
# commas are optional here too, but are syntactically important because
# parameters can be blank
my @arglist = split(/,/, $3);
my @args;
my @args_seperator;
my $comma_sep_required = 0;
foreach (@arglist) {
# allow arithmetic/shift operators in macro arguments
$_ =~ s/\s*(\+|-|\*|\/|<<|>>|<|>)\s*/$1/g;
my @whitespace_split = split(/\s+/, $_);
if (!@whitespace_split) {
push(@args, '');
push(@args_seperator, '');
} else {
foreach (@whitespace_split) {
#print ("arglist = \"$_\"\n");
if (length($_)) {
push(@args, $_);
my $sep = $comma_sep_required ? "," : " ";
push(@args_seperator, $sep);
#print ("sep = \"$sep\", arg = \"$_\"\n");
$comma_sep_required = 0;
}
}
}
$comma_sep_required = 1;
}
my %replacements;
if ($macro_args_default{$macro}){
%replacements = %{$macro_args_default{$macro}};
}
# construct hashtable of text to replace
foreach my $i (0 .. $#args) {
my $argname = $macro_args{$macro}[$i];
my @macro_args = @{ $macro_args{$macro} };
if ($args[$i] =~ m/=/) {
# arg=val references the argument name
# XXX: I'm not sure what the expected behaviour if a lot of
# these are mixed with unnamed args
my @named_arg = split(/=/, $args[$i]);
$replacements{$named_arg[0]} = $named_arg[1];
} elsif ($i > $#{$macro_args{$macro}}) {
# more args given than the macro has named args
# XXX: is vararg allowed on arguments before the last?
$argname = $macro_args{$macro}[-1];
if ($argname =~ s/:vararg$//) {
#print "macro = $macro, args[$i] = $args[$i], args_seperator=@args_seperator, argname = $argname, arglist[$i] = $arglist[$i], arglist = @arglist, args=@args, macro_args=@macro_args\n";
#$replacements{$argname} .= ", $args[$i]";
$replacements{$argname} .= "$args_seperator[$i] $args[$i]";
} else {
die "Too many arguments to macro $macro";
}
} else {
$argname =~ s/:vararg$//;
$replacements{$argname} = $args[$i];
}
}
my $count = $macro_count++;
# apply replacements as regex
foreach (@{$macro_lines{$macro}}) {
my $macro_line = $_;
# do replacements by longest first, this avoids wrong replacement
# when argument names are subsets of each other
foreach (reverse sort {length $a <=> length $b} keys %replacements) {
$macro_line =~ s/\\$_/$replacements{$_}/g;
}
if ($altmacro) {
foreach (reverse sort {length $a <=> length $b} keys %replacements) {
$macro_line =~ s/\b$_\b/$replacements{$_}/g;
}
}
$macro_line =~ s/\\\@/$count/g;
$macro_line =~ s/\\\(\)//g; # remove \()
parse_line($macro_line);
}
} else {
handle_serialized_line($line);
}
}
sub is_arm_register {
my $name = $_[0];
if ($name eq "lr" or
$name eq "ip" or
$name =~ /^[rav]\d+$/) {
return 1;
}
return 0;
}
sub handle_local_label {
my $line = $_[0];
my $num = $_[1];
my $dir