#!/usr/bin/perl
use strict;

# Speicherverbrauch < 100 M mit sample4.txt.
# Laufzeit < 10s auf Intel(R) Pentium(R) 4 CPU 2.60GHz.
# Perlcode in Kompaktform < 20 Zeilen.

# Ersten Parameter @ARGV[0] als Dateiname interpretieren und Datei oeffnen.
# Abbruch, wenn Datei nicht geoeffnet werden kann.

open(IN, @ARGV[0]) or die "Cannot open file '@ARGV[0]': $!\n";

# Gesamte Datei in eine Stringvariable ins RAM lesen, indem Variable $/ (Input
# Record Separator) auf undefiniert gesetzt wird.

undef $/;
my $file = <IN>;

# Nach Fussnoten-Trenner @footnote suchen, Abbruch wenn nicht auffindbar.
# Wichtig: durch den Zusatz 'g' wird bei der naechsten Suche in $file im
# Anschluss an diese Fundstelle pos($file) weitergesucht.

$file =~ /\@footnote/g or die 'Missing marker "@footnote".', "\n";

# $notecount: Anzahl der Fussnotentexte im Verweisteil am Textende.
# @indexmap: Abbildung alte Fussnotennummer auf neue aufsteigende Nummer.
# Leichter lesbar als (my $notecount = 0; my @indexmap) = (0, ());

my $notecount = 0;
my @indexmap = ();

# Alle Fussnotennummern am Textende suchen und als Index im Array @indexmap
# verwenden. Der dem Index zugeordnete Wert ist der aufsteigende Zaehler
# $notecount. Sortierung nicht erforderlich! Beachten: durch die vorherige
# Suche /\@footnote/g wird nur im Verweisteil am Textende gesucht. Durch 'g'
# wird immer das naechste Vorkommnis gefunden. Mit leichter lesbarer
# Darstellung der Schleife:

while ($file =~ /\[(\d+)\]/g) {
   $notecount = $notecount + 1;
   $indexmap[$1] = $notecount
}

# Nun Suchposition auf Anfang der Datei $file im Speicher zuruecksetzen.
pos($file) = 0;

# $from zeigt in $file immer auf die Position nach der letzten gefundenen
# Fussnotenkennung [n], zu Beginn 0.

my $from = 0;

# Alle Fussnotenkennungen der Reihe nach absuchen.

while ($file =~ /\[(\d+)\]/g) {

   # Alle Zeichen nach der letzten Fussnotenkennung bis vor die aktuelle
   # ausgeben. $1 enthaelt als Suchergebnis die Zahl zwischen '[' und ']'.
   # Subtraktion von 2 beruecksichtigt '[' und ']'.

   print substr($file, $from, pos($file) - length($1) - 2 - $from);

   # Die Fussnotenkennung ausgeben, wobei die alte Nummer durch die neu
   # zugewiesene aus dem Array @indexmap ersetzt wird.

   print '[' . $indexmap[$1] . ']';

   # Die Position noch nicht ausgegebenen Textes nachziehen.
   $from = pos($file);
}

# Resttext ausgeben.
print substr($file, $from);