home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / Non-RPC / !Perl / lib / zip / Make.pm < prev    next >
Text File  |  1999-04-05  |  27KB  |  1,294 lines

  1. package Make::Rule::Vars;
  2. use Carp;
  3. use strict;
  4.  
  5. # Package to handle 'magic' variables pertaining to rules e.g. $@ $* $^ $?
  6. # by using tie to this package 'subsvars' can work with array of 
  7. # hash references to possible sources of variable definitions.
  8.  
  9. sub TIEHASH
  10. {
  11.  my ($class,$rule) = @_;
  12.  return bless \$rule,$class;
  13. }
  14.  
  15. sub FETCH
  16. {
  17.  my $self = shift;
  18.  local $_ = shift;
  19.  my $rule = $$self;
  20.  return undef unless (/^[\@^<?*]$/);
  21.  # print STDERR "FETCH $_ for ",$rule->Name,"\n";
  22.  return $rule->Name if ($_ eq '@');
  23.  return $rule->Base if ($_ eq '*');
  24.  return join(' ',$rule->exp_depend)  if ($_ eq '^');
  25.  return join(' ',$rule->out_of_date) if ($_ eq '?');
  26.  # Next one is dubious - I think $< is really more subtle ...
  27.  return ($rule->exp_depend)[0] if ($_ eq '<');
  28.  return undef;
  29. }
  30.  
  31. package Make::Rule;
  32. use Carp;
  33. use strict;
  34.  
  35. # Bottom level 'rule' package 
  36. # An instance exists for each ':' or '::' rule in the makefile.
  37. # The commands and dependancies are kept here.
  38.  
  39. sub target
  40. {
  41.  return shift->{TARGET};
  42. }
  43.  
  44. sub Name
  45. {
  46.  return shift->target->Name;
  47. }
  48.  
  49. sub Base
  50. {
  51.  my $name = shift->target->Name;
  52.  $name =~ s/\.[^.]+$//;
  53.  return $name;
  54. }
  55.  
  56. sub Info
  57. {
  58.  return shift->target->Info;
  59. }
  60.  
  61. sub depend
  62. {
  63.  my $self = shift;
  64.  if (@_)
  65.   {
  66.    my $dep = shift;
  67.    confess "dependants $dep are not an array reference" unless ('ARRAY' eq ref $dep); 
  68.    my $file;
  69.    foreach $file (@$dep)
  70.     {
  71.      unless (exists $self->{DEPHASH}{$file})
  72.       {
  73.        $self->{DEPHASH}{$file} = 1;
  74.        push(@{$self->{DEPEND}},$file);
  75.       }
  76.     }
  77.   }
  78.  return (wantarray) ? @{$self->{DEPEND}} : $self->{DEPEND};
  79. }
  80.  
  81. sub command
  82. {
  83.  my $self = shift;
  84.  if (@_)
  85.   {
  86.    my $cmd = shift;
  87.    confess "commands $cmd are not an array reference" unless ('ARRAY' eq ref $cmd); 
  88.    if (@$cmd)
  89.     {
  90.      if (@{$self->{COMMAND}})
  91.       {
  92.        warn "Command for ".$self->Name," redefined";
  93.        print STDERR "Was:",join("\n",@{$self->{COMMAND}}),"\n";
  94.        print STDERR "Now:",join("\n",@$cmd),"\n";
  95.       }
  96.      $self->{COMMAND} = $cmd;
  97.     }
  98.    else
  99.     {
  100.      if (@{$self->{COMMAND}})
  101.       { 
  102.        # warn "Command for ".$self->Name," retained";
  103.        # print STDERR "Was:",join("\n",@{$self->{COMMAND}}),"\n";
  104.       }
  105.     } 
  106.   }
  107.  return (wantarray) ? @{$self->{COMMAND}} : $self->{COMMAND};
  108. }
  109.  
  110. #
  111. # The key make test - is target out-of-date as far as this rule is concerned
  112. # In scalar context - boolean value of 'do we need to apply the rule'
  113. # In list context the things we are out-of-date with e.g. magic $? variable
  114. #
  115. sub out_of_date
  116. {
  117.  my $self  = shift;
  118.  my $info  = $self->Info;
  119.  my @dep = ();
  120.  my $tdate  = $self->target->date;
  121.  my $dep;
  122.  my $count = 0;
  123.  foreach $dep ($self->exp_depend)
  124.   {
  125.    my $date = $info->date($dep);
  126.    $count++;
  127.    if (!defined($date) || !defined($tdate) || $date < $tdate)
  128.     {
  129.      push(@dep,$dep);
  130.     }
  131.   }
  132.  # Note special case of no dependencies means it is always  out-of-date!
  133.  return (wantarray) ? @dep : (!$count || @dep);
  134. }
  135.  
  136. #
  137. # Return list of things rule depends on with variables expanded
  138. # - May need pathname and vpath processing as well
  139. #
  140. sub exp_depend
  141. {
  142.  my $self = shift;
  143.  my $info = $self->Info;
  144.  my @dep = map(split(/\s+/,$info->subsvars($_)),$self->depend);
  145.  return (wantarray) ? @dep : \@dep;
  146. }
  147.  
  148. #
  149. # Return commands to apply rule with variables expanded
  150. # - No pathname processing needed, commands should always chdir()
  151. #   to logical place (at least till we get very clever at bourne shell parsing).
  152. # - May need vpath processing
  153. #
  154. sub exp_command
  155. {
  156.  my $self   = shift;
  157.  my $info   = $self->Info;
  158.  my $base   = $self->Name;
  159.  my %var;
  160.  tie %var,'Make::Rule::Vars',$self;
  161.  my @cmd  = map($info->subsvars($_,\%var),$self->command);
  162.  return (wantarray) ? @cmd : \@cmd;
  163. }
  164.  
  165. #
  166. # clone creates a new rule derived from an existing rule, but 
  167. # with a different target. Used when left hand side was a variable.
  168. # perhaps should be used for dot/pattern rule processing too.
  169. #
  170. sub clone
  171. {
  172.  my ($self,$target) = @_;
  173.  my %hash = %$self;
  174.  $hash{TARGET} = $target;
  175.  return bless \%hash,ref $self;
  176. }
  177.  
  178. sub new
  179. {
  180.  my $class = shift;
  181.  my $target = shift;
  182.  my $kind   = shift;
  183.  # return shift->clone($target) if (@_ == 1);
  184.  my $self = bless { TARGET => $target,             # parent target (left hand side)
  185.                     KIND => $kind,                 # : or ::
  186.                     DEPEND => [], DEPHASH => {},   # right hand args
  187.                     COMMAND => []                  # command(s)  
  188.                   },$class;        
  189.  $self->depend(shift) if (@_);
  190.  $self->command(shift) if (@_);
  191.  return $self;
  192. }
  193.  
  194. #
  195. # This code has to go somewhere but no good home obvious yet.
  196. #  - only applies to ':' rules, but needs top level database
  197. #  - perhaps in ->commands of derived ':' class?
  198. #
  199. sub find_commands
  200. {
  201.  my ($self) = @_;
  202.  if (!@{$self->{COMMAND}} && @{$self->{DEPEND}})
  203.   {
  204.    my $info = $self->Info;
  205.    my $name = $self->Name;
  206.    my @dep  = $self->depend;
  207.    my @rule = $info->patrule($self->Name);
  208.    if (@rule)
  209.     {
  210.      $self->depend($rule[0]);
  211.      $self->command($rule[1]);
  212.     }
  213.   }
  214. }
  215.  
  216. #
  217. # Spew a shell script to perfom the 'make' e.g. make -n 
  218. #
  219. sub Script
  220. {
  221.  my $self = shift;
  222.  return unless $self->out_of_date;
  223.  my @cmd = $self->exp_command;
  224.  if (@cmd)
  225.   {
  226.    my $file;
  227.   my $com = ($^O eq 'MSWin32') ? 'rem ': ($^O eq 'riscos') ? '| ' : '# ';
  228.    print  $com,$self->Name,"\n";
  229.    foreach $file ($self->exp_command)
  230.     {
  231.      $file =~ s/^[\@\s-]*//;
  232.      print "$file\n";
  233.     }
  234.   }
  235. }
  236.  
  237. #
  238. # Normal 'make' method
  239. #
  240. sub Make
  241. {
  242.  my $self = shift;
  243.  my $file;
  244.  return unless $self->out_of_date;
  245.  my @cmd = $self->exp_command;
  246.  my $info = $self->Info;
  247.  if (@cmd)
  248.   {
  249.    # print "# ",$self->Name,"\n";
  250.    foreach my $file ($self->exp_command)
  251.     {
  252.      $file =~ s/^([\@\s-]*)//;
  253.      my $prefix = $1;
  254.      print  "$file\n" unless ($prefix =~ /\@/);
  255.      my $code = $info->exec($file);
  256.      if ($code && $prefix !~ /-/)
  257.       {
  258.        die "Code $code from $file";
  259.       }
  260.     }
  261.   }
  262. }
  263.  
  264. #
  265. # Print rule out in makefile syntax 
  266. # - currently has variables expanded as debugging aid.
  267. # - will eventually become make -p 
  268. # - may be useful for writing makefiles from MakeMaker too...
  269. #
  270. sub Print
  271. {
  272.  my $self = shift;
  273.  my $file;
  274.  print $self->Name,' ',$self->{KIND},' ';
  275.  foreach $file ($self->exp_depend)
  276.   {
  277.    print " \\\n   $file";
  278.   }
  279.  print "\n";
  280.  my @cmd = $self->exp_command;
  281.  if (@cmd)
  282.   {
  283.    foreach $file ($self->exp_command)
  284.     {
  285.      print "\t",$file,"\n";
  286.     }
  287.   }
  288.  else
  289.   {
  290.    print STDERR "No commands for ",$self->Name,"\n" unless ($self->target->phony); 
  291.   }
  292.  print "\n";
  293. }
  294.  
  295. package Make::Target;
  296. use Carp;
  297. use strict;
  298. use Cwd;
  299.  
  300. #
  301. # Intermediate 'target' package
  302. # There is an instance of this for each 'target' that apears on 
  303. # the left hand side of a rule i.e. for each thing that can be made.
  304. sub new
  305. {
  306.  my ($class,$info,$target) = @_;
  307.  return bless { NAME => $target,     # name of thing
  308.                 MAKEFILE => $info,   # Makefile context 
  309.                 Pass => 0            # Used to determine if 'done' this sweep
  310.               },$class;
  311. }
  312.  
  313. sub date
  314. {
  315.  my $self = shift;
  316.  my $info = $self->Info;
  317.  return $info->date($self->Name);
  318. }
  319.  
  320. sub phony
  321. {
  322.  my $self = shift;
  323.  return $self->Info->phony($self->Name);
  324. }
  325.  
  326. sub colon
  327. {
  328.  my $self = shift;
  329.  if (@_)
  330.   {
  331.    if (exists $self->{COLON})
  332.     {
  333.      my $dep = $self->{COLON};
  334.      if (@_ == 1)
  335.       {
  336.        my $other = shift;
  337.        $dep->depend(scalar $other->depend);
  338.        $dep->command(scalar $other->command);
  339.       }
  340.      else
  341.       {
  342.        $dep->depend(shift);
  343.        $dep->command(shift);
  344.       }
  345.     }
  346.    else
  347.     {
  348.      $self->{COLON} = (@_ == 1) ? shift->clone($self) : Make::Rule->new($self,':',@_);
  349.     }
  350.   }
  351.  if (exists $self->{COLON})
  352.   {
  353.    return (wantarray) ? ($self->{COLON}) : $self->{COLON};
  354.   }
  355.  else
  356.   {
  357.    return (wantarray) ? () : undef;
  358.   }
  359. }
  360.  
  361. sub dcolon
  362. {
  363.  my $self = shift;
  364.  if (@_)
  365.   {
  366.    my $rule = (@_ == 1) ? shift->clone($self) : Make::Rule->new($self,'::',@_);
  367.    $self->{DCOLON} = [] unless (exists $self->{DCOLON});
  368.    push(@{$self->{DCOLON}},$rule);
  369.   }
  370.  return (exists $self->{DCOLON}) ? @{$self->{DCOLON}} : ();
  371. }
  372.  
  373. sub Name
  374. {
  375.  return shift->{NAME};
  376. }
  377.  
  378. sub Info
  379. {
  380.  return shift->{MAKEFILE};
  381. }
  382.  
  383. sub ProcessColon
  384. {
  385.  my ($self) = @_;
  386.  my $c = $self->colon;
  387.  $c->find_commands if $c;
  388. }
  389.  
  390. sub ExpandTarget
  391. {
  392.  my ($self) = @_;
  393.  my $target = $self->Name;
  394.  my $info   = $self->Info;
  395.  my $colon  = delete $self->{COLON};
  396.  my $dcolon = delete $self->{DCOLON};
  397.  foreach my $expand (split(/\s+/,$info->subsvars($target)))
  398.   {
  399.    next unless defined($expand);
  400.    my $t = $info->Target($expand);
  401.    if (defined $colon)
  402.     {
  403.      $t->colon($colon); 
  404.     }
  405.    foreach my $d (@{$dcolon})
  406.     {
  407.      $t->dcolon($d);
  408.     }
  409.   }
  410. }
  411.  
  412. sub done
  413. {
  414.  my $self = shift;
  415.  my $info = $self->Info;
  416.  my $pass = $info->pass;
  417.  return 1 if ($self->{Pass} == $pass);
  418.  $self->{Pass} = $pass;
  419.  return 0;
  420. }
  421.  
  422. sub recurse
  423. {
  424.  my ($self,$method,@args) = @_;
  425.  my $info = $self->Info;
  426.  my $rule;
  427.  foreach $rule ($self->colon,$self->dcolon)
  428.   {
  429.    my $dep;
  430.    foreach $dep ($rule->exp_depend)
  431.     {
  432.      my $t = $info->{Depend}{$dep};
  433.      if (defined $t)
  434.       {
  435.        $t->$method(@args) 
  436.       }
  437.      else
  438.       {
  439.        my $dir = cwd(); 
  440.        die "Cannot recurse $method - no target $dep in $dir" unless ($info->exists($dep));
  441.       }
  442.     }
  443.   }
  444. }
  445.  
  446. sub Script
  447. {
  448.  my $self = shift;
  449.  my $info = $self->Info;
  450.  my $rule = $self->colon;
  451.  return if ($self->done);
  452.  $self->recurse('Script');
  453.  foreach $rule ($self->colon,$self->dcolon)
  454.   {
  455.    $rule->Script;
  456.   }
  457. }
  458.  
  459. sub Make
  460. {
  461.  my $self = shift;
  462.  my $info = $self->Info;
  463.  my $rule = $self->colon;
  464.  return if ($self->done);
  465.  $self->recurse('Make');
  466.  foreach $rule ($self->colon,$self->dcolon)
  467.   {
  468.    $rule->Make;
  469.   }
  470. }
  471.  
  472. sub Print
  473. {
  474.  my $self = shift;
  475.  my $info = $self->Info;
  476.  return if ($self->done);
  477.  my $rule = $self->colon;
  478.  foreach $rule ($self->colon,$self->dcolon)
  479.   {
  480.    $rule->Print;
  481.   }
  482.  $self->recurse('Print');
  483. }
  484.  
  485. package Make;
  486. use 5.005;  # Need look-behind assertions
  487. use Carp;
  488. use strict;
  489. use Config;
  490. use Cwd;
  491. use File::Spec;
  492. use vars qw($VERSION);
  493. $VERSION = '0.03';
  494.  
  495. sub phony
  496. {
  497.  my ($self,$name) = @_;
  498.  return exists $self->{PHONY}{$name};
  499. }
  500.  
  501. sub suffixes
  502. {
  503.  my ($self) = @_;
  504.  return keys %{$self->{'SUFFIXES'}};
  505. }
  506.  
  507. #
  508. # Construct a new 'target' (or find old one)
  509. # - used by parser to add to data structures
  510. #
  511. sub Target
  512. {
  513.  my ($self,$target) = @_;
  514.  unless (exists $self->{Depend}{$target})
  515.   {
  516.    my $t = Make::Target->new($self,$target);
  517.    $self->{Depend}{$target} = $t;
  518.   if ($target =~ /%/)
  519.    {
  520.     $self->{Pattern}{$target} = $t;
  521.    }
  522.   elsif ($target =~ /^\./)
  523.    {
  524.     $self->{Dot}{$target} = $t;
  525.    }
  526.   else
  527.    {
  528.     push(@{$self->{Targets}},$t);
  529.    }
  530.   }
  531.  return $self->{Depend}{$target};
  532. }
  533.  
  534. #
  535. # Utility routine for patching %.o type 'patterns'
  536. #
  537. sub patmatch
  538. {
  539.  my $key = shift;
  540.  local $_ = shift;
  541.  my $pat = $key;
  542.  $pat =~ s/\./\\./;
  543.  $pat =~ s/%/(\[^\/\]*)/;
  544.  if (/$pat$/)
  545.   {
  546.    return $1;
  547.   }
  548.  return undef;
  549. }
  550.  
  551. #
  552. # old vpath lookup routine 
  553. #
  554. sub locate
  555. {
  556.  my $self = shift;
  557.  local $_ = shift;
  558.  return $_ if (-r $_);
  559.  my $key;
  560.  foreach $key (keys %{$self->{vpath}})
  561.   {
  562.    my $Pat;
  563.    if (defined($Pat = patmatch($key,$_)))
  564.     {
  565.      my $dir;
  566.      foreach $dir (split(/:/,$self->{vpath}{$key}))
  567.       {
  568.        return "$dir/$_"  if (-r "$dir/$_");
  569.       }
  570.     }
  571.   }
  572.  return undef;
  573. }
  574.  
  575. #
  576. # Convert traditional .c.o rules into GNU-like into %o : %c
  577. #
  578. sub dotrules
  579. {
  580.  my ($self) = @_;
  581.  my $t;
  582.  foreach $t (keys %{$self->{Dot}})
  583.   {
  584.    my $e = $self->subsvars($t);
  585.    $self->{Dot}{$e} = delete $self->{Dot}{$t} unless ($t eq $e);
  586.   }
  587.  my (@suffix) = $self->suffixes;
  588.  foreach $t (@suffix)
  589.   {
  590.    my $d;
  591.    my $r = delete $self->{Dot}{$t};
  592.    if (defined $r)
  593.     {
  594.      my @rule = ($r->colon) ? $r->colon->depend : ();
  595.      if (@rule)
  596.       {
  597.        delete $self->{Dot}{$t->Name};
  598.        print STDERR $t->Name," has dependants\n";
  599.        push(@{$self->{Targets}},$r);
  600.       }
  601.      else
  602.       {
  603.        # print STDERR "Build \% : \%$t\n";                   
  604.        $self->Target('%')->dcolon(['%'.$t],scalar $r->colon->command);
  605.       }
  606.     }
  607.    foreach $d (@suffix)
  608.     {
  609.      $r = delete $self->{Dot}{$t.$d};
  610.      if (defined $r)
  611.       {
  612.        # print STDERR "Build \%$d : \%$t\n";
  613.        $self->Target('%'.$d)->dcolon(['%'.$t],scalar $r->colon->command);
  614.       }
  615.     }
  616.   }
  617.  foreach $t (keys %{$self->{Dot}})
  618.   {
  619.    push(@{$self->{Targets}},delete $self->{Dot}{$t});
  620.   }
  621. }
  622.  
  623. #
  624. # Return 'full' pathname of name given directory info. 
  625. # - may be the place to do vpath stuff ?
  626. #
  627. sub pathname
  628. {
  629.  my ($self,$name) = @_;
  630.  return $name if File::Spec->file_name_is_absolute($name);
  631.  $name =~ s,^\./,,;
  632.  return File::Spec->catfile($self->{Dir},$name);
  633. }
  634.  
  635. #
  636. # Return modified date of name if it exists
  637. sub date
  638. {
  639.  my ($self,$name) = @_;
  640.  my $path = $self->pathname($name);
  641.  my $r = -M $path;
  642.  # print STDERR "$path date is $r\n" if (defined $r);
  643.  return $r;
  644. }
  645.  
  646. #
  647. # Check to see if name is a target we can make or an existing
  648. # file - used to see if pattern rules are valid
  649. # - Needs extending to do vpath lookups
  650. #
  651. sub exists
  652. {
  653.  my ($self,$name) = @_;
  654.  return 1 if (exists $self->{Depend}{$name});
  655.  my $path = $self->pathname($name);
  656.  return 1 if (-e $path);
  657.  # print STDERR "$name '$path' does not exist\n";
  658.  return 0;
  659. }
  660.  
  661. #
  662. # See if we can find a %.o : %.c rule for target
  663. # .c.o rules are already converted to this form 
  664. #
  665. sub patrule
  666. {
  667.  my ($self,$target) = @_;
  668.  my $key;
  669.  # print STDERR "Trying pattern for $target\n";
  670.  foreach $key (keys %{$self->{Pattern}})
  671.   {
  672.    my $Pat;
  673.    if (defined($Pat = patmatch($key,$target)))
  674.     {
  675.      my $t = $self->{Pattern}{$key};
  676.      my $rule;
  677.      foreach $rule ($t->dcolon)
  678.       {
  679.        my @dep = $rule->exp_depend;
  680.        if (@dep)
  681.         {
  682.          my $dep = $dep[0];
  683.          $dep =~ s/%/$Pat/g;
  684.          # print STDERR "Try $target : $dep\n";
  685.          if ($self->exists($dep)) 
  686.           {
  687.            foreach (@dep)
  688.             {
  689.              s/%/$Pat/g;
  690.             }
  691.            return (\@dep,scalar $rule->command);
  692.           }
  693.         }
  694.       }
  695.     }
  696.   }
  697.  return ();
  698. }
  699.  
  700. #
  701. # Old code to handle vpath stuff - not used yet
  702. #
  703. sub needs
  704. {my ($self,$target) = @_;
  705.  unless ($self->{Done}{$target})
  706.   {
  707.    if (exists $self->{Depend}{$target})
  708.     {
  709.      my @depend = split(/\s+/,$self->subsvars($self->{Depend}{$target}));
  710.      foreach (@depend)
  711.       {
  712.        $self->needs($_);
  713.       }
  714.     }
  715.    else
  716.     {
  717.      my $vtarget = $self->locate($target);
  718.      if (defined $vtarget)
  719.       {
  720.        $self->{Need}{$vtarget} = $target;
  721.       }
  722.      else
  723.       {
  724.        $self->{Need}{$target}  = $target;
  725.       }
  726.     }
  727.   }
  728. }
  729.  
  730. #
  731. # Substitute $(xxxx) and $x style variable references
  732. # - should handle ${xxx} as well
  733. # - recurses still they all go rather than doing one level,
  734. #   which may need fixing
  735. #
  736. sub subsvars
  737. {
  738.  my $self = shift;
  739.  local $_ = shift;
  740.  my @var = @_;
  741.  push(@var,$self->{Override},$self->{Vars},\%ENV);
  742.  croak("Trying to subsitute undef value") unless (defined $_); 
  743.  while (/(?<!\$)\$\(([^()]+)\)/ || /(?<!\$)\$([<\@^?*])/)
  744.   {
  745.    my ($key,$head,$tail) = ($1,$`,$');
  746.    my $value;
  747.    if ($key =~ /^([\w._]+|\S)(?::(.*))?$/)
  748.     {
  749.      my ($var,$op) = ($1,$2);
  750.      foreach my $hash (@var)
  751.       {
  752.        $value = $hash->{$var};
  753.        if (defined $value)
  754.         {
  755.          last; 
  756.         }
  757.       }
  758.      unless (defined $value)
  759.       {
  760.        die "$var not defined in '$_'" unless (length($var) > 1); 
  761.        $value = '';
  762.       }
  763.      if (defined $op)
  764.       {
  765.        if ($op =~ /^s(.).*\1.*\1/)
  766.         {
  767.          local $_ = $self->subsvars($value);
  768.          $op =~ s/\\/\\\\/g;
  769.          eval $op.'g';
  770.          $value = $_;
  771.         }
  772.        else
  773.         {
  774.          die "$var:$op = '$value'\n"; 
  775.         }   
  776.       }
  777.     }
  778.    elsif ($key =~ /wildcard\s*(.*)$/)
  779.     {
  780.      $value = join(' ',glob($self->pathname($1)));
  781.     }
  782.    elsif ($key =~ /shell\s*(.*)$/)
  783.     {
  784.      $value = join(' ',split('\n',`$1`));
  785.     }
  786.    elsif ($key =~ /addprefix\s*([^,]*),(.*)$/)
  787.     {
  788.      $value = join(' ',map($1 . $_,split('\s+',$2)));
  789.     }
  790.    elsif ($key =~ /notdir\s*(.*)$/)
  791.     {
  792.      my @files = split(/\s+/,$1);
  793.      foreach (@files)
  794.       {
  795.        s#^.*/([^/]*)$#$1#;
  796.       }
  797.      $value = join(' ',@files);
  798.     }
  799.    elsif ($key =~ /dir\s*(.*)$/)
  800.     {
  801.      my @files = split(/\s+/,$1);
  802.      foreach (@files)
  803.       {
  804.        s#^(.*)/[^/]*$#$1#;
  805.       }
  806.      $value = join(' ',@files);
  807.     }
  808.    elsif ($key =~ /^subst\s+([^,]*),([^,]*),(.*)$/)
  809.     {
  810.      my ($a,$b) = ($1,$2);
  811.      $value = $3;
  812.      $a =~ s/\./\\./;
  813.      $value =~ s/$a/$b/; 
  814.     }
  815.    elsif ($key =~ /^mktmp,(\S+)\s*(.*)$/)
  816.     {
  817.      my ($file,$content) = ($1,$2);
  818.      open(TMP,">$file") || die "Cannot open $file:$!";
  819.      $content =~ s/\\n//g;
  820.      print TMP $content;
  821.      close(TMP);
  822.      $value = $file;
  823.     }
  824.    else
  825.     {
  826.      warn "Cannot evaluate '$key' in '$_'\n";
  827.     }
  828.    $_ = "$head$value$tail";
  829.   }
  830.  s/\$\$/\$/g;
  831.  return $_;
  832. }
  833.  
  834. #
  835. # Split a string into tokens - like split(/\s+/,...) but handling
  836. # $(keyword ...) with embedded \s
  837. # Perhaps should also understand "..." and '...' ?
  838. #
  839. sub tokenize
  840. {
  841.  local $_ = $_[0];
  842.  my @result = ();
  843.  s/\s+$//;
  844.  while (length($_))
  845.   {
  846.    s/^\s+//;
  847.    last unless (/^\S/);
  848.    my $token = "";
  849.    while (/^\S/)
  850.     {
  851.      if (s/^\$([\(\{])//)
  852.       {
  853.        $token .= $&; 
  854.        my $paren = $1 eq '(';
  855.        my $brace = $1 eq '{';
  856.        my $count = 1;
  857.        while (length($_) && ($paren || $brace))
  858.         {
  859.          s/^.//;
  860.          $token .= $&; 
  861.          $paren += ($& eq '(');
  862.          $paren -= ($& eq ')');
  863.          $brace += ($& eq '{');
  864.          $brace -= ($& eq '}');
  865.         }
  866.        die "Mismatched {} in $_[0]" if ($brace);
  867.        die "Mismatched () in $_[0]" if ($paren);
  868.       }
  869.      elsif (s/^(\$\S?|[^\s\$]+)//)
  870.       {
  871.        $token .= $&;
  872.       }
  873.     }
  874.    push(@result,$token);
  875.   }
  876.  return (wantarray) ? @result : \@result;
  877. }
  878.  
  879.  
  880. #
  881. # read makefile (or fragment of one) either as a result
  882. # of a command line, or an 'include' in another makefile.
  883. sub makefile
  884. {
  885.  my ($self,$makefile,$name) = @_;
  886.  local $_;
  887.  print STDERR "Reading $name\n";
  888. Makefile:
  889.  while (<$makefile>)
  890.   {
  891.    last unless (defined $_);
  892.    chomp($_);
  893.    if (/\\$/)
  894.     {
  895.      chop($_);
  896.      s/\s*$//;
  897.      my $more = <$makefile>;
  898.      $more =~ s/^\s*/ /; 
  899.      $_ .= $more;
  900.      redo;
  901.     }
  902.    next if (/^\s*#/);
  903.    next if (/^\s*$/);
  904.    s/#.*$//;
  905.    s/^\s+//;
  906.    if (/^(-?)include\s+(.*)$/)
  907.     {
  908.      my $opt = $1;
  909.      my $file;
  910.      foreach $file (tokenize($self->subsvars($2)))
  911.       {
  912.        local *Makefile;
  913.        my $path = $self->pathname($file);
  914.        if (open(Makefile,"<$path"))
  915.         {
  916.          $self->makefile(\*Makefile,$path);
  917.          close(Makefile);
  918.         }
  919.        else
  920.         {
  921.          warn "Cannot open $path:$!" unless ($opt eq '-') ;
  922.         }
  923.       }
  924.     }
  925.    elsif (/^\s*([\w._]+)\s*:?=\s*(.*)$/)
  926.     {
  927.      $self->{Vars}{$1} = (defined $2) ? $2 : "";
  928. #    print STDERR "$1 = ",$self->{Vars}{$1},"\n";
  929.     }
  930.    elsif (/^vpath\s+(\S+)\s+(.*)$/)
  931.     {my ($pat,$path) = ($1,$2);
  932.      $self->{Vpath}{$pat} = $path;
  933.     }
  934.    elsif (/^\s*([^:]*)(::?)\s*(.*)$/)
  935.     {
  936.      my ($target,$kind,$depend) = ($1,$2,$3);
  937.      my @cmnds;
  938.      if ($depend =~ /^([^;]*);(.*)$/)
  939.       {
  940.        ($depend,$cmnds[0])  = ($1,$2);
  941.       }
  942.      while (<$makefile>)
  943.       {
  944.        next if (/^\s*#/);
  945.        next if (/^\s*$/);
  946.        last unless (/^\t/);
  947.        chop($_);         
  948.        if (/\\$/)        
  949.         {                
  950.          chop($_);
  951.          $_ .= ' ';
  952.          $_ .= <$makefile>;
  953.          redo;           
  954.         }                
  955.        next if (/^\s*$/);
  956.        s/^\s+//;
  957.        push(@cmnds,$_);
  958.       }
  959.      $depend =~ s/\s\s+/ /;
  960.      $target =~ s/\s\s+/ /;
  961.      my @depend = tokenize($depend);
  962.      foreach (tokenize($target))
  963.       {
  964.        my $t = $self->Target($_);
  965.        my $index = 0;
  966.        if ($kind eq '::' || /%/)
  967.         {
  968.          $t->dcolon(\@depend,\@cmnds);
  969.         }
  970.        else
  971.         {
  972.          $t->colon(\@depend,\@cmnds);
  973.         }
  974.       }
  975.      redo Makefile;
  976.     }
  977.    else
  978.     {
  979.      warn "Ignore '$_'\n";
  980.     }
  981.   }
  982. }
  983.  
  984. sub pseudos
  985. {
  986.  my $self = shift;
  987.  my $key;
  988.  foreach $key (qw(SUFFIXES PHONY PRECIOUS PARALLEL))
  989.   {
  990.    my $t = delete $self->{Dot}{'.'.$key};
  991.    if (defined $t)
  992.     {
  993.      my $dep;
  994.      $self->{$key} = {};
  995.      foreach $dep ($t->colon->exp_depend)
  996.       {
  997.        $self->{$key}{$dep} = 1;
  998.       }
  999.     }
  1000.   }
  1001. }
  1002.  
  1003.  
  1004. sub ExpandTarget
  1005. {
  1006.  my $self = shift;
  1007.  foreach my $t (@{$self->{'Targets'}})
  1008.   {
  1009.    $t->ExpandTarget;
  1010.   }
  1011.  foreach my $t (@{$self->{'Targets'}})
  1012.   {
  1013.    $t->ProcessColon;
  1014.   }
  1015. }
  1016.  
  1017. sub parse
  1018. {
  1019.  my ($self,$file) = @_;
  1020.  if (defined $file)
  1021.   {
  1022.    $file = $self->pathname($file);
  1023.   }
  1024.  else
  1025.   {
  1026.    my @files = qw(makefile Makefile);
  1027.    unshift(@files,'GNUmakefile') if ($self->{GNU});
  1028.    my $name;
  1029.    foreach $name (@files)
  1030.     {
  1031.      $file = $self->pathname($name);
  1032.      if (-r $file)
  1033.       {
  1034.        $self->{Makefile} = $name;
  1035.        last; 
  1036.       }
  1037.     }
  1038.   }
  1039.  local (*Makefile);
  1040.  open(Makefile,"<$file") || croak("Cannot open $file:$!");
  1041.  $self->makefile(\*Makefile,$file);
  1042.  close(Makefile);
  1043.  
  1044.  # Next bits should really be done 'lazy' on need.
  1045.  
  1046.  $self->pseudos;         # Pull out .SUFFIXES etc. 
  1047.  $self->dotrules;        # Convert .c.o into %.o : %.c
  1048. }
  1049.  
  1050. sub PrintVars
  1051. {
  1052.  my $self = shift;
  1053.  local $_;
  1054.  foreach (keys %{$self->{Vars}})
  1055.   {
  1056.    print "$_ = ",$self->{Vars}{$_},"\n";
  1057.   }
  1058.  print "\n";
  1059. }
  1060.  
  1061. sub exec
  1062. {
  1063.  my $self = shift;
  1064.  if ($^O eq 'MSWin32' or $^O eq 'riscos')
  1065.   {
  1066.    my $cwd = cwd();
  1067.    my $ret;
  1068.    chdir $self->{Dir};
  1069.    if ($^O eq 'riscos') {
  1070.       my $com = join ' ', @_;
  1071.       $com =~ tr/\t/ /;
  1072.       # shortcut known no-ops (OSCLI comments start with a '|')
  1073.       $ret = ($com =~ /^\*\|/) ? 0 : system('dumbshell', '-c', $com);
  1074.    } else {
  1075.       $ret = system(@_);
  1076.    }
  1077.    chdir $cwd;
  1078.    return $ret;
  1079.   }
  1080.  else
  1081.   {
  1082.    my $pid  = fork;
  1083.    if ($pid)
  1084.     {
  1085.      waitpid $pid,0;
  1086.      return $?;
  1087.     }
  1088.    else
  1089.     {
  1090.      my $dir = $self->{Dir}; 
  1091.      chdir($dir) || die "Cannot cd to $dir";
  1092.      # handle leading VAR=value here ?
  1093.      # To handle trivial cases like ': libpTk.a' force using /bin/sh
  1094.      exec("/bin/sh","-c",@_) || confess "Cannot exec ".join(' ',@_);
  1095.     }
  1096.   }
  1097. }
  1098.  
  1099. sub NextPass { shift->{Pass}++ }
  1100. sub pass     { shift->{Pass} }
  1101.  
  1102. sub apply
  1103. {
  1104.  my $self = shift;
  1105.  my $method = shift;
  1106.  $self->NextPass;
  1107.  my @targets = ();
  1108.  # print STDERR join(' ',Apply => $method,@_),"\n";
  1109.  foreach (@_)
  1110.   {
  1111.    if (/^(\w+)=(.*)$/)
  1112.     {
  1113.      # print STDERR "OVERRIDE: $1 = $2\n";
  1114.      $self->{Override}{$1} = $2;
  1115.     }
  1116.    else
  1117.     {
  1118.      push(@targets,$_);
  1119.     }
  1120.   }
  1121.  #
  1122.  # This expansion is dubious as it alters the database
  1123.  # as a function of current values of Override.
  1124.  # 
  1125.  $self->ExpandTarget;    # Process $(VAR) : 
  1126.  @targets = ($self->{'Targets'}[0])->Name unless (@targets);
  1127.  # print STDERR join(' ',Targets => $method,map($_->Name,@targets)),"\n";
  1128.  foreach (@targets)
  1129.   {
  1130.    my $t = $self->{Depend}{$_};
  1131.    unless (defined $t)
  1132.     {
  1133.      print STDERR join(' ',$method,@_),"\n";
  1134.      die "Cannot `$method' - no target $_" 
  1135.     }
  1136.    $t->$method();
  1137.   }
  1138. }
  1139.  
  1140. sub Script
  1141. {
  1142.  shift->apply(Script => @_);
  1143. }
  1144.  
  1145. sub Print
  1146. {
  1147.  shift->apply(Print => @_);
  1148. }
  1149.  
  1150. sub Make
  1151. {
  1152.  shift->apply(Make => @_);
  1153. }
  1154.  
  1155. sub new
  1156. {
  1157.  my ($class,%args) = @_;
  1158.  unless (defined $args{Dir})
  1159.   {
  1160.    chomp($args{Dir} = cwd());
  1161.   }
  1162.  my $self = bless { %args, 
  1163.                    Pattern  => {},  # GNU style %.o : %.c 
  1164.                    Dot      => {},  # Trad style .c.o
  1165.                    Vpath    => {},  # vpath %.c info 
  1166.                    Vars     => {},  # Variables defined in makefile
  1167.                    Depend   => {},  # hash of targets
  1168.                    Targets  => [],  # ordered version so we can find 1st one
  1169.                    Pass     => 0,   # incremented each sweep
  1170.                    Need     => {},
  1171.                    Done     => {},
  1172.                  },$class;
  1173.  $self->{Vars}{CC}     = $Config{cc};
  1174.  $self->{Vars}{AR}     = $Config{ar};
  1175.  $self->{Vars}{CFLAGS} = $Config{optimize};
  1176.  $self->makefile(\*DATA,__FILE__);
  1177.  $self->parse($self->{Makefile});
  1178.  return $self;
  1179. }
  1180.  
  1181. =head1 NAME
  1182.  
  1183. Make - module for processing makefiles 
  1184.  
  1185. =head1 SYNOPSIS
  1186.  
  1187.     require Make;
  1188.     my $make = Make->new(...);
  1189.     $make->parse($file);   
  1190.     $make->Script(@ARGV)
  1191.     $make->Make(@ARGV)
  1192.     $make->Print(@ARGV)
  1193.  
  1194.         my $targ = $make->Target($name);
  1195.         $targ->colon([dependancy...],[command...]);
  1196.         $targ->dolon([dependancy...],[command...]);
  1197.         my @depends  = $targ->colon->depend;
  1198.         my @commands = $targ->colon->command;
  1199.  
  1200. =head1 DESCRIPTION
  1201.  
  1202. Make->new creates an object if C<new(Makefile =E<gt> $file)> is specified
  1203. then it is parsed. If not the usual makefile Makefile sequence is 
  1204. used. (If GNU => 1 is passed to new then GNUmakefile is looked for first.) 
  1205.  
  1206. C<$make-E<gt>Make(target...)> 'makes' the target(s) specified
  1207. (or the first 'real' target in the makefile).
  1208.  
  1209. C<$make-E<gt>Print> can be used to 'print' to current C<select>'ed stream
  1210. a form of the makefile with all variables expanded. 
  1211.  
  1212. C<$make-E<gt>Script(target...)> can be used to 'print' to 
  1213. current C<select>'ed stream the equivalent bourne shell script
  1214. that a make would perform i.e. the output of C<make -n>.
  1215.  
  1216. There are other methods (used by parse) which can be used to add and 
  1217. manipulate targets and their dependants. There is a hierarchy of classes
  1218. which is still evolving. These classes and their methods will be documented when
  1219. they are a little more stable.
  1220.  
  1221. The syntax of makefile accepted is reasonably generic, but I have not re-read
  1222. any documentation yet, rather I have implemented my own mental model of how
  1223. make works (then fixed it...).
  1224.  
  1225. In addition to traditional 
  1226.  
  1227.     .c.o : 
  1228.         $(CC) -c ...
  1229.  
  1230. GNU make's 'pattern' rules e.g. 
  1231.  
  1232.     %.o : %.c 
  1233.         $(CC) -c ...
  1234.  
  1235. Likewise a subset of GNU makes $(function arg...) syntax is supported.
  1236.  
  1237. Via pmake Make has built perl/Tk from the C<MakeMaker> generated Makefiles...
  1238.  
  1239. =head1 BUGS
  1240.  
  1241. At present C<new> must always find a makefile, and
  1242. C<$make-E<gt>parse($file)> can only be used to augment that file.
  1243.  
  1244. More attention needs to be given to using the package to I<write> makefiles.
  1245.  
  1246. The rules for matching 'dot rules' e.g. .c.o   and/or pattern rules e.g. %.o : %.c
  1247. are suspect. For example give a choice of .xs.o vs .xs.c + .c.o behaviour
  1248. seems a little odd.
  1249.  
  1250. Variables are probably substituted in different 'phases' of the process
  1251. than in make(1) (or even GNU make), so 'clever' uses will probably not
  1252. work.
  1253.  
  1254. UNIXisms abound. 
  1255.  
  1256. =head1 SEE ALSO 
  1257.  
  1258. L<pmake>
  1259.  
  1260. =head1 AUTHOR
  1261.  
  1262. Nick Ing-Simmons
  1263.  
  1264. =cut 
  1265.  
  1266. 1;
  1267. #
  1268. # Remainder of file is in makefile syntax and constitutes
  1269. # the built in rules
  1270. #
  1271. __DATA__
  1272.  
  1273. .SUFFIXES: .o .c .y .h .sh .cps
  1274.  
  1275. .c.o :
  1276.     $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 
  1277.  
  1278. .c   :
  1279.     $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $< $(LDFLAGS) $(LDLIBS)
  1280.  
  1281. .y.o:
  1282.     $(YACC) $<
  1283.     $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ y.tab.c
  1284.     $(RM) y.tab.c
  1285.  
  1286. .y.c:
  1287.     $(YACC) $<
  1288.     mv y.tab.c $@
  1289.  
  1290.  
  1291.