summaryrefslogtreecommitdiff
path: root/mcon/pl/locate.pl
diff options
context:
space:
mode:
Diffstat (limited to 'mcon/pl/locate.pl')
-rw-r--r--mcon/pl/locate.pl153
1 files changed, 153 insertions, 0 deletions
diff --git a/mcon/pl/locate.pl b/mcon/pl/locate.pl
new file mode 100644
index 0000000..ce3e065
--- /dev/null
+++ b/mcon/pl/locate.pl
@@ -0,0 +1,153 @@
+;# $Id: locate.pl,v 3.0.1.1 1994/10/29 16:36:52 ram Exp $
+;#
+;# Copyright (c) 1991-1993, Raphael Manfredi
+;#
+;# You may redistribute only under the terms of the Artistic Licence,
+;# as specified in the README file that comes with the distribution.
+;# You may reuse parts of this distribution only within the terms of
+;# that same Artistic Licence; a copy of which may be found at the root
+;# of the source tree for dist 3.0.
+;#
+;# $Log: locate.pl,v $
+;# Revision 3.0.1.1 1994/10/29 16:36:52 ram
+;# patch36: misspelled a 'closedir' as a 'close' statement
+;#
+;# Revision 3.0 1993/08/18 12:10:25 ram
+;# Baseline for dist 3.0 netwide release.
+;#
+;#
+;# Locate units and put them in the @ARGV array, for later perusal. We first
+;# look in the private U directory, then in the public U library. In each U
+;# directory, units may be gathered in clusters (directories). These clusters
+;# should not have a name ending with .U, as those will never be stat()'ed.
+;#
+;# NB: Currently, the clusters are only a practical way of grouping a set of
+;# closely related units. There must not be any name conflicts.
+;#
+;# The following variables are used:
+;# $WD is assumed to be the working directory (where the process was spawned)
+;# $MC is the location of metaconfig's public library
+;# @ARGV is the list of all the units full path
+;# %Unit maps an unit name (without final .U) to a path
+;# @myUlist lists the user's units, which will be appended at the end of @ARGV
+;# %myUseen lists the user's units which overwrite public ones
+;#
+package locate;
+
+# Locate the units and push their path in @ARGV (sorted alphabetically)
+sub main'locate_units {
+ print "Locating units...\n" unless $main'opt_s;
+ local(*WD) = *main'WD; # Current working directory
+ local(*MC) = *main'MC; # Public metaconfig library
+ undef %myUlist; # Records private units paths
+ undef %myUseen; # Records private/public conflicts
+ &private_units; # Locate private units in @myUlist
+ &public_units; # Locate public units in @ARGV
+ @ARGV = sort @ARGV; # Sort it alphabetically
+ push(@ARGV, sort @myUlist); # Append user's units sorted
+ &dump_list if $main'opt_v; # Dump the list of units
+}
+
+# Dump the list of units on stdout
+sub dump_list {
+ print "\t";
+ $, = "\n\t";
+ print @ARGV;
+ $, = '';
+ print "\n";
+}
+
+# Scan private units
+sub private_units {
+ return unless -d 'U'; # Nothing to be done if no 'U' entry
+ local(*ARGV) = *myUlist; # Really fill in @myUlist
+ local($MC) = $WD; # We are really in the working directory
+ &units_path("U"); # Locate units in the U directory
+ local($unit_name); # Unit's name (without .U)
+ local(@kept); # Array of kept units
+ # Loop over the units and remove duplicates (the first one seen is the one
+ # we keep). Also set the %myUseen H table to record private units seen.
+ foreach (@ARGV) {
+ ($unit_name) = m|^.*/(.*)\.U$|; # Get unit's name from path
+ next if $myUseen{$unit_name}; # Already recorded
+ $myUseen{$unit_name} = 1; # Record pirvate unit
+ push(@kept, $_); # Keep this unit
+ }
+ @ARGV = @kept;
+}
+
+# Scan public units
+sub public_units {
+ chdir($MC) || die "Can't find directory $MC.\n";
+ &units_path("U"); # Locate units in public U directory
+ chdir($WD) || die "Can't go back to directory $WD.\n";
+ local($path); # Relative path from $WD
+ local($unit_name); # Unit's name (without .U)
+ local(*Unit) = *main'Unit; # Unit is a global from main package
+ local(@kept); # Units kept
+ local(%warned); # Units which have already issued a message
+ # Loop over all the units and keep only the ones that were not found in
+ # the user's U directory. As it is possible two or more units with the same
+ # name be found in
+ foreach (@ARGV) {
+ ($unit_name) = m|^.*/(.*)\.U$|; # Get unit's name from path
+ next if $warned{$unit_name}; # We have already seen this unit
+ $warned{$unit_name} = 1; # Remember we have warned the user
+ if ($myUseen{$unit_name}) { # User already has a private unit
+ $path = $Unit{$unit_name}; # Extract user's unit path
+ next if $path eq $_; # Same path, we must be in mcon/
+ $path =~ s|^$WD/||o; # Weed out leading working dir path
+ print " Your private $path overrides the public one.\n"
+ unless $main'opt_s;
+ } else {
+ push(@kept, $_); # We may keep this one
+ }
+ }
+ @ARGV = @kept;
+}
+
+# Recursively locate units in the directory. Each file ending with .U has to be
+# a unit. Others are stat()'ed, and if they are a directory, they are also
+# scanned through. The $MC and @ARGV variable are dynamically set by the caller.
+sub units_path {
+ local($dir) = @_; # Directory where units are to be found
+ local(@contents); # Contents of the directory
+ local($unit_name); # Unit's name, without final .U
+ local($path); # Full path of a unit
+ local(*Unit) = *main'Unit; # Unit is a global from main package
+ unless (opendir(DIR, $dir)) {
+ warn("Cannot open directory $dir.\n");
+ return;
+ }
+ print "Locating in $MC/$dir...\n" if $main'opt_v;
+ @contents = readdir DIR; # Slurp the whole thing
+ closedir DIR; # And close dir, ready for recursion
+ foreach (@contents) {
+ next if $_ eq '.' || $_ eq '..';
+ if (/\.U$/) { # A unit, definitely
+ ($unit_name) = /^(.*)\.U$/;
+ $path = "$MC/$dir/$_"; # Full path of unit
+ push(@ARGV, $path); # Record its path
+ if (defined $Unit{$unit_name}) { # Already seen this unit
+ if ($main'opt_v) {
+ ($path) = $Unit{$unit_name} =~ m|^(.*)/.*|;
+ print " We've already seen $unit_name.U in $path.\n";
+ }
+ } else {
+ $Unit{$unit_name} = $path; # Map name to path
+ }
+ next;
+ }
+ # We have found a file which does not look like a unit. If it is a
+ # directory, then scan it. Otherwise skip the file.
+ unless (-d "$dir/$_") {
+ print " Skipping file $_ in $dir.\n" if $main'opt_v;
+ next;
+ }
+ &units_path("$dir/$_");
+ print "Back to $MC/$dir...\n" if $main'opt_v;
+ }
+}
+
+package main;
+