cvsuser     01/09/19 21:08:16

  Modified:    .        assemble.pl
  Log:
  macro expansion.  Here's the test macro I was using:
  
  # this uses I32,I31 as temporaries.
  # macro must be preceeded by a label.
  testi macro   num,got,want
        print   "Test #"
        print   num
        print   "..."
        set     I32,want
        set     I31,got
        eq      I32,I31,$ok
        print   "NG\n"
        branch  $end
  $ok:  print   "OK\n"
  $end:
        endm
  
  It is invoked as:
  
  Test1:        testi   1,I3,I2
  
  Revision  Changes    Path
  1.32      +114 -59   parrot/assemble.pl
  
  Index: assemble.pl
  ===================================================================
  RCS file: /home/perlcvs/parrot/assemble.pl,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -w -r1.31 -r1.32
  --- assemble.pl       2001/09/20 01:49:55     1.31
  +++ assemble.pl       2001/09/20 04:08:16     1.32
  @@ -18,7 +18,7 @@
                      'listing=s'));
   
   if($options{'version'}) {
  -    print $0,'Version $Id: assemble.pl,v 1.31 2001/09/20 01:49:55 bdwheele Exp $ 
',"\n";
  +    print $0,'Version $Id: assemble.pl,v 1.32 2001/09/20 04:08:16 bdwheele Exp $ 
',"\n";
       exit;
   }
   
  @@ -81,21 +81,29 @@
   # assemble
   my $pc=0; my $op_pc=0;
   my ($bytecode,%label,%fixup,%constants,@constants);
  -my (%local_label, %local_fixup, $last_label);
  +my (%local_label, %local_fixup, $last_label, %macros);
   my $line=0;
   my %equate=('*'=>sub { return $pc },
            '__DATE__'=>'"'.scalar(localtime).'"',
  -         '__VERSION__'=>'" $Revision: 1.31 $ "',
  +         '__VERSION__'=>'" $Revision: 1.32 $ "',
            '__LINE__' => sub { return $line });
  -foreach my $l (@program) {
  +my($code,$in_macro,$cur_macro);
  +while(my $l=shift(@program)) {
       my($file,$line,$pline,$sline)=@$l;
  -    if($pline=~m/^\#/ || $pline eq "") {
  -     if($options{'listing'}) {
  -         $listing.=sprintf("%4d %08x %-44s %s\n", $line, $op_pc, '',$sline);
  +    if($in_macro) {
  +     if($pline=~m/^endm$/i) {
  +         # end of the macro
  +         $in_macro=0;
  +     } else {
  +         push(@{$macros{$cur_macro}[1]},$l);
        }
  -     next;
  +     $pline="";
       }
  -    my($label,$code);
  +    if($pline=~m/^\#/ || $pline eq "") {
  +     # its a comment, do nothing
  +     $code=undef;
  +    } else {
  +     my($label);
       if($pline=~m/^(\S+):\s*(.+)?/) {
           ($label,$code)=($1,$2);
        if(defined($label) && $label ne "") {
  @@ -145,14 +153,61 @@
        if($pline=~m/^([_a-zA-Z]\w*)\s+equ\s+(.+)$/i) {
            my($name,$data)=($1,$2);
            $equate{$name}=$data;
  +         } elsif($pline=~m/^([_a-zA-Z]\w*)\s+macro\s+(.+)$/i) {
  +             # a macro definition
  +             my($name,$args)=($1,$2);
  +             $cur_macro=$name;
  +             $macros{$name}=[[split(/,\s*/,$args)],[]];
  +             $in_macro=1;
        } else {
            $code=$pline;
        }
  +     }
  +    }
  +    if(!defined($code)) {
  +     $listing.=sprintf("%4d %08x %-44s %s\n", $line, $op_pc, '',$sline)
  +         if($options{'listing'});
  +     next;
       }
  -    next if(!defined($code));
  +
       1 while $code=~s/\"([^\\\"]*(?:\\.[^\\\"]*)*)\"/constantize($1)/eg;
       $code=~s/,/ /g;
       my($opcode,@args)=split(/\s+/,$code);
  +    if(exists($macros{$opcode})) {
  +     # found a macro
  +     my(@margs)=@{$macros{$opcode}[0]};
  +     my(@macro);
  +     # we have to make sure to copy the macro, to avoid mangling the
  +     # original macro definition.
  +     foreach (@{$macros{$opcode}[1]}) {
  +         push(@macro,[@$_]);
  +     }
  +     if(scalar(@margs) != scalar(@args)) {
  +         error("Wrong number of arguments to macro '$opcode'",$file,$line);
  +     }
  +     # fixup parameters.
  +     while(my $marg=shift(@margs)) {
  +         my $param=shift(@args);
  +         foreach (@macro) {
  +             $_->[2]=~s/([\s,])$marg\b/$1$param/g;
  +             $_->[3]=~s/([\s,])$marg\b/$1$param/g;
  +         }
  +     }
  +
  +     # fixup file, line number, listing
  +     foreach (@macro) {
  +         $_->[0]=$file;
  +         $_->[1]=$line;
  +         $_->[3]="> ".$_->[3];
  +     }
  +     unshift(@program,@macro);
  +
  +     # make it come out correctly on the listing.
  +     $l->[2]='';
  +     unshift(@program,$l);
  +     next;
  +    }
  +    
       $opcode=lc($opcode);
       if (!exists $opcodes{$opcode}) {
        # try to determine _real_ opcode.
  @@ -311,7 +366,7 @@
   
   # FIXUP (also, dump listing symbols)
   if($options{'listing'}) {
  -    $listing.="DEFINED SYMBOLS:\n";
  +    $listing.="\nDEFINED SYMBOLS:\n";
       foreach (sort(keys(%label))) {
        $listing.=sprintf("\t%08x   %s\n",$label{$_},$_);
       }
  
  
  

Reply via email to