Instead of handling macros and repetitions in two passes, with
.if handling spread out over the two, handle both at the same
time.
---
 gas-preprocessor.pl | 171 ++++++++++++++++++++++++++--------------------------
 test.S              |   4 ++
 2 files changed, 88 insertions(+), 87 deletions(-)

diff --git a/gas-preprocessor.pl b/gas-preprocessor.pl
index d6779cd..5a048ec 100755
--- a/gas-preprocessor.pl
+++ b/gas-preprocessor.pl
@@ -216,6 +216,12 @@ my $macro_count = 0;
 my $altmacro = 0;
 my $in_irp = 0;
 
+my $num_repts;
+my @rept_lines;
+
+my @irp_args;
+my $irp_param;
+
 my @pass1_lines;
 my @ifstack;
 
@@ -327,27 +333,27 @@ sub parse_line {
 
     return if (parse_if_line($line));
 
-    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 (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;
+            }
         }
-    } elsif (/\.irp/ or /\.rept/) {
-        $in_irp = 1;
-    } elsif (/.endr/) {
-        $in_irp = 0;
     }
 
     if ($macro_level > 1) {
         push(@{$macro_lines{$current_macro}}, $line);
+    } elsif (scalar(@rept_lines) and $line !~ /\.endr/) {
+        push(@rept_lines, $line);
     } elsif ($macro_level == 0) {
         expand_macros($line);
     } else {
@@ -390,7 +396,7 @@ sub expand_macros {
 
     # handle .if directives; apple's assembler doesn't support important 
non-basic ones
     # evaluating them is also needed to handle recursive macros
-    if (!$in_irp && handle_if($line)) {
+    if (handle_if($line)) {
         return;
     }
 
@@ -415,7 +421,65 @@ sub expand_macros {
 
     handle_set($line);
 
-    if ($line =~ /(\S+:|)\s*([\w\d\.]+)\s*(.*)/ && exists $macro_lines{$2}) {
+    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}) {
         push(@pass1_lines, $1);
         my $macro = $2;
 
@@ -513,8 +577,6 @@ if ($ENV{GASPP_DEBUG}) {
 }
 
 my @sections;
-my $num_repts;
-my @rept_lines;
 
 my %literal_labels;     # for ldr <reg>, =<expr>
 my $literal_num = 0;
@@ -527,9 +589,6 @@ my %thumb_labels;
 my %call_targets;
 my %mov32_targets;
 
-my @irp_args;
-my $irp_param;
-
 my %neon_alias_reg;
 my %neon_alias_type;
 
@@ -541,7 +600,7 @@ my %labels_seen;
 
 my %aarch64_req_alias;
 
-# pass 2: parse .rept and .if variants
+# pass 2
 foreach my $line (@pass1_lines) {
     # handle .previous (only with regard to .section not .subsection)
     if ($line =~ /\.(section|text|const_data)/) {
@@ -625,73 +684,11 @@ foreach my $line (@pass1_lines) {
         }
     }
 
-    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/) {
-        if ($in_irp != 0) {
-            foreach my $i (@irp_args) {
-                foreach my $origline (@rept_lines) {
-                    my $line = $origline;
-                    $line =~ s/\\$irp_param/$i/g;
-                    $line =~ s/\\\(\)//g;     # remove \()
-                    handle_serialized_line($line, 1);
-                }
-            }
-        } else {
-            for (1 .. $num_repts) {
-                foreach my $origline (@rept_lines) {
-                    my $line = $origline;
-                    handle_serialized_line($line, 1);
-                }
-            }
-        }
-        @rept_lines = ();
-        $in_irp = 0;
-        @irp_args = '';
-    } elsif (scalar(@rept_lines)) {
-        push(@rept_lines, $line);
-    } else {
-        handle_serialized_line($line, 0);
-    }
+    handle_serialized_line($line);
 }
 
 sub handle_serialized_line {
     my $line = @_[0];
-    my $do_eval_if = @_[1];
-
-    if ($do_eval_if) {
-        return if parse_if_line($line);
-        return if handle_if($line);
-    }
 
     # Strip out the .set lines from the armasm output
     return if (handle_set($line) and $as_type eq "armasm");
diff --git a/test.S b/test.S
index a849616..a05e743 100644
--- a/test.S
+++ b/test.S
@@ -26,3 +26,7 @@ m 0
         mov r3, #42
     .endif
 .endr
+
+.irpc i, 01
+    m \i
+.endr
-- 
1.8.5.2 (Apple Git-48)

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to