use strict;
use warnings;

my $ref = parse_config("test.cfg");

foreach my $key (sort keys(%{$ref}))
  { 
  print "$key => $ref->{$key}\n"; 
  }

  
sub parse_config
  {
  my $file   = shift;             # Dateinamen holen
  my $config = {};                # Referenz auf einen leeren Hash
  my $count  = 0;                 # Zeilenzähler
  my $group  = '';                # Gruppenbezeichner
  my ($line, $key, $value);       # Arbeitsvariablen 
  
  open(CF,"<", $file) or die "Oops! $file: $!";
 
  while ($line = <CF>)
   {
   $count++;
   chomp($line);                  # Newline weg
   next if($line =~ m/^\s*#/);    # Kommentarzeile ignorieren
   next if $line =~ m/^\s*$/;     # Leerzeilen ignorieren

   # Gruppenbezeichner verarbeiten
   if ($line =~ m/^\s*\[(.*)\]\s*$/)
     {
     $group = $1 . "_";
     next;
     }

   if ($line !~ m/^\s*\S+\s*=.*$/) # sieht nicht nach "Key = Value" aus? 
     {
     warn "*** moeglicher Fehler in Zeile $count; von $file\n";
     next;
     }
     

   # Zeile zerlegen, alles hinter dem "=" kommt nach $value  
   ($key,$value) = split(/=/, $line, 2); 


   # Blanks rund um den Key entfernen
   $key   =~ s/^\s+//g;
   $key   =~ s/\s+$//g;
   # Gruppenbezeichner dazu
   $key = $group . $key;
   
   # End-Kommentare in $value entfernen
   $value =~ s/#.*$//;
   # Blanks rund um $value entfernen
   $value =~ s/^\s+//g;
   $value =~ s/\s+$//g;
   # Anfuehrungszeichen bei $value entfernen
   $value =~ s/^['"]//g;
   $value =~ s/['"]$//g;
   # Newlines bei $value bearbeiten
   $value =~ s/\\n/\n/g;
   

   # gegebenenfalls auch CR am Ende entfernen
   $value =~ s/\015$//;

   # Doubletten bearbeiten
   if(exists $config->{$key})
     { warn "*** doppelter Schluessel ($key) in Zeile $count; von $file\n"; }
   
   # rekursive Definitionen (A = B, C = A, D = C) behandeln
   while (exists $config->{$value})
     {
     warn "*** $key intern auf $config->{$value} geaendert\n"; 
     $value = $config->{$value};
     }
   # Daten in den Hash aufnehmen
   $config->{$key} = $value;
   }
  close(CF);
  return $config;
  }
