#!/usr/bin/perl
use strict;
use warnings;
use Cwd;

# Name:         dirname-ng
# Author(s):    Manuel Fill ( manuel.fill@egger.com )
# Function:     Anders als dirname aus dem coreutils-Package welches
#               . und .. nicht als Current Directory bzw Parent-Directory
#               erkennt, tut dieses Programm das.
#               Ausserdem kann dieses Programm mit mehreren Pfadangaben
#               umgehen als das coreutils-Package.
#
# Use:          ./dirname-ng [ FILE(S) ]
#               ./dirname-ng -
#               - liest vom Standardinputkanal ein
#               ./dirname-ng -h oder --help
#               - zeigt Infos an
#
# Version:      0.1 ( 2007-02-19 )
#               - Initial Release
#               0.2 ( 2007-02-20 )
#               - Current Working Directory eingebaut
#               0.3 ( 2007-02-21 )
#               - dirname-ng kann nun von STDIN lesen
#
# Bitte jegliche Veraenderung des Quelltextes kommentieren und den Autor informieren!

# Globale Variablen

our $version = "0.3 ( 2007-02-21 )";
if( @ARGV < 1 ) {   # Wenn kein Parameter uebergeben wurde ...
  &usage;           # ... Zeig die usage-Meldung ...
  print STDERR "\ndirname-ng benoetigt mindestens einen Parameter!\n\n";
  exit 1;           # ... und verabschiede dich mit einer Meldung
}

if( @ARGV == 1 ) {  # Wenn nur EIN Parameter uebergeben wurde ...
  if( $ARGV[0] eq "--help" or $ARGV[0] eq "-h") {
    &usage;         # wenn -h oder --help dann usage anzeigen
    exit 0;         # und beenden
  }
    
  if( $ARGV[0] eq "-" ) {     # wenn - der Parameter ist ...
    while(<STDIN>) {          # lese die STDIN-Liste zeilenweise aus
      chomp;
      push @ARGV, $_;         # und schreib sie ins ARGV-Array
    }
    shift @ARGV;
  }
}

foreach ( @ARGV ) {                 # Argumentliste verarbeiten   
  if( substr( $_ , 0, 1) ne "/") {  # Wenn kein Slash am Beginn steht ...
    $_ = cwd . "/$_";               # ... fuege das cwd an den Beginn an
  }

  &step_one( split /\//, $_ );      # Der Fkt. die Directories ohne "/" uebergeben
}

sub step_one {
  my @after_step_one;         # Variable, die nachher der zweiten Fkt. uebergeben wird
  foreach (@_) {              # Argumentliste verarbeiten
    if ( $_ ne "" ) {         # wenn nicht // eingegeben wurde
      push @after_step_one, $_;	# Wert ans Ende des Arrays schreiben
    }
  }
    
  &step_two(@after_step_one); # Der zweiten Funktion das Array uebergeben
}

sub step_two {
  my @after_step_two;         # Variable die schlussendlich den Valid Pfad enthaelt
  my $run_parent = 0;         # Counter der Parent-Directories ( .. )
  for (0 .. @_ - 1 ) {        # Argumentliste verarbeiten
    if ( $_[$_] eq "." ) {    # Wenn "." im Array vorkommt ( und NUR das ) ...
      $_[$_] = "";            # ... wandel es zu einem Leerstring um. ( das ist ok, das Directory 
    }                         # aendert sich dadurch ja nicht )

    if ( $_[$_] eq ".." ) {   # Wenn ".." im Array vorkommt ( und NUR das ) ...
      if( $_ != 0 ) {         # Wenn wir nicht im Root-Dir ( / ) stehen ( cd /../ waere Bloedsinn )
        $run_parent++;        # Counter der Parent-Dirs um ein erhoehen
        $_[$_ - ( $run_parent + ( $run_parent - 1 ))] = ""; # entsprechendes Parent Directory im Array
      }                       # leeren ( "" ) ( Siehe Berechnung am Ende )

      $_[$_] = "";            # ebenso das Feld in dem ".." stand leeren
    } else {                  # Falls Arrayfeld nicht ".." ist ...
      $run_parent = 0;        # ... Counter-Reset auf 0
    }
  }
  foreach ( @_) {               # Die neue Argumentliste verarbeiten
    if ( $_ ne "" ) {           # Wenn das Array-Feld nicht leer ( "" ) ist
      push @after_step_two, $_; # Neues Array ohne die Leerfelder erstellen
    }
  }
    
  for ( 0 .. @after_step_two - 2 ) {  # Array verarbeiten
	  print "/$after_step_two[$_]";     # Formatierte Ausgabe der Pfad-Teilfelder
	}
    
  if (@after_step_two < 2) {    # Wenn das Array eigentlich leer ist ... ( wir sind im root-dir )
    print "/";                  # ... gib / aus.
  }

  print "\n";                   # Ein Newline pro Pfad
}

sub usage {
  print "dirname-ng $version\n";
  print "\nUsage:\n";
  print "\t\tdirname-ng [ FILE(S) ]  Standardaufruf mit Datei(en) als Parameter\n";
  print "\t\tdirname-ng -            Liest eine Liste vom Standardinput ein\n";
  print "\t\tdirname-ng --help       Zeigt diesen Output\n\n";
  print "Beispiele:\n";
  print "----------\n";
  print "\tdirname-ng /tmp/testfile /opt/scripts/test /root\nergibt:\n";
  print "\t/tmp\n\t/opt/scripts\n\t/\n\n\n";
  print "\tfind /opt/scripts/* | dirname-ng - | sort | uniq \nergibt:\n";
  print "\t/opt\n\t/opt/scripts\n\t/opt/scripts/cluster\n\t";
  print "/opt/scripts/collect\n\t/opt/scripts/lk\n\t/opt/scripts/oracle\n\t";
  print "/opt/scripts/san\n\t/opt/scripts/san/logs\n\t/opt/scripts/siga\n\n"; 
  print "Fehler, Verbesserungsvorschlaege, Kritik zu diesem Programm an \<manuel.fill\@egger.com\>\n";
}

# Berechnung der Parent Directories:
# Beispiel: Pfadangabe /tmp/test1/test2/test3/../../testfile
#	  -> ist somit /tmp/test1/testfile
#
#	Arraypos. = Wert    $counterwert    Berechnung des Loeschindex
# ------------------------------------------------------------------------------------
#	$array[0] = tmp	        0				
#	$array[1] = test1       0
#	$array[2] = test2       0
#	$array[3] = test3       0
#	$array[4] = ..          1         4 - ( 1 + ( 1 - 1 ) = 3 -> array[3]
#	$array[5] = ..          2         5 - ( 2 + ( 2 - 1 ) = 2 -> array[2]
#	$array[6] = testfile    0
#
#
# Somit ist das neue Array nach Leerung der entsprechenden Array-Felder:
#
#	Arraypos. = Wert
# -------------------------------------------------------------------------------------
#	$array[0] = tmp
#	$array[1] = test1
#	$array[2] = 
#	$array[3] = 
#	$array[4] = 
#	$array[5] = 
#	$array[6] = testfile

