<?php
/**
* Read text with footnotes from the input stream, reordering the footnote
* numbers starting from 1.
* Written-for and tested on PHP 5.2.6.
**/
// PHP is typically configured for short-lived Web page rendering applications
// Since this app may potentially be working on very large data sets, remove
// execution time limits, and increase maximum memory consumption.
ini_set('max_execution_time', 0);
ini_set('memory_limit', '512m');
// Handle command line
if (isset($_SERVER['argv'][1])) {
$filename = $_SERVER['argv'][1];
} else {
$filename = 'php://stdin';
}
// Open input file
$infp = fopen($filename, "r");
if (!$infp) {
exit("Unable to open '$filename' for input.\n");
}
// Close input stream and terminate (not strictly necessary)
fclose($infp);
exit();
/////////////////////////////////////////////////////////////////////
/////////// Utility functions (can be in a separate file) ///////////
/////////////////////////////////////////////////////////////////////
/**
* Read the text block and reorder the footnotes as we go
* (automatically maintains a translation table from old footnote numbers
* to new ones)
*
* @param fileStream $infp
*/
function handleTextBlock($infp)
{
define('FOOTNOTE_HEADER', '@footnote:');
define('FOOTNOTE_HEADER_LENGTH', strlen(FOOTNOTE_HEADER));
// Stop if we reached the footnote target section
if ($line[0]=='@' && strncmp($line, FOOTNOTE_HEADER, FOOTNOTE_HEADER_LENGTH)==0) {
break;
}
}
}
/**
* Handle reordering of the footnotes in-memory
* @param fileStream $infp
*/
function handleFootnotesBlockInMemory($infp)
{
// Reorder footnotes if needed, and print them out
$footnoteTargets = array();
// Iterate over footnote lines
while ($line = fgets($infp)) {
// If line doesn't seem to be a footnote, print as-is
if ($line[0] != '[') {
echo $line;
continue;
}
// Get the footnote key (number) and value (text)
list($key, $val) = explode(' ', $line, 2);
$key = Footnotes::translate(trim($key, '[]'));
/**
* Translate a given footnote number according to the translation table
*
* If the footnote numer is encountered for the first time, a new entry
* will be added to the conversion table
*
* @param integer $number
* @return integer
*/
static public function translate($number)
{
if (! isset(self::$_table[$number])) {
self::$_table[$number] = ++self::$_count;
}
return self::$_table[$number];
}
/**
* A callback function wrapping self::translate() for use with preg_replace_callback
* @param array $match
* @return string
*/
static public function replaceCallback($match)
{
return '[' . self::translate($match[1]) . ']';
}
}