#!/usr/bin/perl # -*- perl -*- # Copyright (C) 2006 Red Hat Inc. # # This file is part of GAS, the GNU Assembler. # # GAS is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # GAS is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GAS; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. */ %myfiles = (); $incdir = "."; while ($ARGV[0] =~ /^-/) { $opt = shift; if ($opt eq "-I") { $incdir = shift; } } $infile = shift; $outfile = shift; $inbase = $infile; $inbase =~ s@.*/@@; $inbase =~ s@[^a-zA-Z0-9].*@@; $t = 0; $errors = 0; if ($outfile) { open(OUT, ">$outfile"); } else { open(OUT, ">&STDOUT"); } open(I, "$incdir/macros.inc") || die("$incdir/macros.inc: $!"); &read_file(); close I; open(I, $infile) || die("$infile: $!"); &read_file(); close I; sub read_file { while () { $line ++; next if /^;/; s/[\r\n]+$//; if (/^macro\s+(\S+)\s+(.*)/) { ($name, $val) = ($1,$2); print "set macro \"$name\" to \"$val\"\n" if $t; $macro{$name} = $val; } elsif (/\S/) { &explode($_); } } } exit ($errors); # There's no way to quote braces so you can output them :-P sub explode { my ($s) = @_; my ($a, $b, $p, $e, @params); print "explode($s)\n" if $t; ($b, $a, @params) = &split_braces($s); @params = explode_params (@params); if (! $a && ! @params) { if ($t) { print "\033[33m$s\033[0m\n"; } else { print OUT "$s\n"; } return; } if (@params == 1 && defined $macro{$params[0]}) { $p = $macro{$params[0]}; &explode ("$b$p$a"); } else { for $p (@params) { &explode ("$b$p$a"); } } } sub explode_params { my (@p) = @_; my ($p,@r); @r = (); while (@p) { $p = shift @p; ($b,$a,@e) = split_braces ($p); if (defined $a) { for $e (reverse @e) { unshift (@p, "$b$e$a"); } } else { push (@r, $p); } } return @r; } sub getmacro { my ($v) = $macro{$_[0]}; if (! defined $v) { print STDERR "$line: Error: macro $_[0] not defined\n"; $errors ++; } return $v; } sub expand_macros { my ($l) = @_; 0 while $l =~ s/{([^{};]+)}/&getmacro($1)/ge; return $l; } # returns (before, after, list of variances) sub split_braces { my ($l) = @_; my (@l, $i, $a, @parms, $b, $n,$p); print "split_braces($l) = (" if $t; $l = &expand_macros ($l); if ($l !~ /\{.*\}/) { print "nothing)\n" if $t; return ($l); } if ($l =~ /^{([^{};]+)}/) { print "macro:", $macro{$1}, ")\n" if $t; return (&getmacro($1), ""); } $n = 0; @parms = (''); $p = 0; ($a, $l) = $l =~ m@^([^\{]*)\{(.*)@; @l = split(//, $l); while (defined ($i = shift @l)) { if ($n == 0) { print "\033[32m$i" if $t; if ($i eq '}') { print "\033[0m$a, ", join('', @l), ", (", join("\033[31m;\033[0m", @parms), ")\n" if $t; return ($a, join('',@l), @parms); } elsif ($i eq ';') { $p ++; $parms[$p] = ''; } else { $parms[$p] .= $i; $n ++ if $i eq '{'; } } else { print "\033[34m$i" if $t; $n ++ if $i eq '{'; $n -- if $i eq '}'; $parms[$p] .= $i; } } print "$a, , (", join(';', @parms), ")\n" if $t; return ($a, "", @parms); } __END__; macro rest c,d foo {a;b},{{rest};e;} expands to: foo a,c foo a,d foo a,e foo a, foo b,c foo b,d foo b,e foo b,