<?php// This PHP script generates clickable HTML documentation files for amforth// project. Script should be run once (offline) when new versions of sorces are// available. It creates new subdirectory with HTML documentation tree.//// Default configuration is in file GenerateHTML.cfg//// Command Line paramaters are available via php GenerateHTML.php --help//// (c)miho 2007 / http://www.mlab.cz// **********************************************************************// History// **********************************************************************// 0.00 work wersion// 0.01 basic functionality// **********************************************************************// Definitions/parameters// **********************************************************************define ('INCLUDE_PATTERN', "/^ *\.include +\"(\S+)\"/i");define ('LABEL_PREFIX', "(VE_|XT_|PFA)");define ('LABEL_PATTERN', "/^ *(".LABEL_PREFIX."\S+):/i");define ('WORD_PATTERN', "/((?:\\n *;.*)*)\\n *VE_Q:[^\\n]*\\n? *.db +[^,]* *, *(\S[^\\n|;]+)/im"); // Q is used instead of Worddefine ('ASMFILES', "CodeAsm/");// **********************************************************************// Generic Funcions// **********************************************************************function Error($ErrorStr)// If ErrorStr is not empty print it and die{if ($ErrorStr=="")return;print "\n";print " ERROR: -->".$ErrorStr."\n";die(1);}function MyReadFile($FileName, &$FileContent)// Reads file, returns file as a single string{//if ($FileName=="")return "No File Name";// Read file$FileContent=@file($FileName);// Test if file contains any contentif ($FileContent==FALSE)return "No Data in File: $FileName";// Remove CR or LF or CR/LFforeach($FileContent as $Key => $Line){$FileContent[$Key]=rtrim($Line);}// No errorreturn "";}function MyReadFileString($FileName, &$FileContent)// Reads file and returns its content as a single string{// No Error$Error="";// Read file$Error=MyReadFile($FileName, &$FileContent);// Convert to a single stringif ($Error=="") $FileContent=implode("\n",$FileContent);// Finishedreturn $Error;}function MyWriteFile($FileName, $FileContent)// Creates and writes file{// Create Output File$File=@fopen($FileName,"w");if ($File==FALSE){return "Unable Write File ".$FileName;}// Write contentfwrite($File,$FileContent);fclose($File);// No Errorreturn "";}function FileName2HTML($FileName)// Converts FileName to FileName of HTML file{// Remove path$FileName=basename($FileName);// Change suffix$FileName=preg_replace("/\.asm$/i",".html",$FileName);// Finished#print $FileName;return $FileName;}function Label2Link($Link, $href, $title, &$LabelList)// Converts Label to Link// If label not found returns original text// IN $Link - label to find// IN $Word - word to show (on mouse)// IN $LabelList - list of all labels (Label, FileName, LineNumber){// Find label in $LabelListforeach($LabelList as $Value){if ($Link===$Value["Label"]){#$LabelListItem=$Value /////////////////////////////print "Found ".$Value["Label"]."\n";}}$FileName=$Value["FileName"]."#".$Link;// Create link$Link="<a href=\"".$FileName."\" title=\" ".$Word."\">".$Link.'</a>';return $Link;}// **********************************************************************// Function for processing// **********************************************************************function Help()// Display help{print "\n";print "This script takes default parameters from GenerateHTML.cfg.\n";print "\n";print "Parameters can be entered directly on command line as well:\n";print " php GenerateHTML.php par1=val1 par2=val2\n";print "\n";print "Sometimes (in Windows) it is necessary to use quotation marks this way:\n";print " php GenerateHTML.php \"par1=val1\" \"par2=val2\"\n";print "\n";print "Parameters are: \n";print " EnableApache={0|1} - Enable to run in Apache\n";print " SourceDir=path - path to asm source directory\n";print " SourceAsm=file - name of top level asm source file\n";print " SvnInfoFileName - name of Svn Info File\n";print " TemplateDir=path - path to HTML template\n";print " DestinationDir=path - path to destination HTML\n";Error("\n");}function Parameters(&$CFG)// Function process Command Line parameters{// Dummy values$CFG["EnableApache"] = 0; // Do not allow run in Apache$CFG["SourceDir"] = "";$CFG["SourceAsm"] = "";$CFG["SvnInfoFileName"] = "";$CFG["TemplateDir"] = "";$CFG["DestinationDir"] = "";// Default values (in cfg file)@include_once("GenerateHTML.cfg");// Command Line parametersif ($_SERVER["argc"]>1){// Helpif ($_SERVER["argv"][1]=="--help")Help();// Dropunset($_SERVER["argv"][0]);// Go through argumentsforeach($_SERVER["argv"] as $Key => $Value){$Left=substr($Value,0,strpos($Value,"="));$Right=substr($Value,strpos($Value,"=")+1);if (isset($CFG[$Left]) && $Right!="" ){$CFG[$Left]=$Right;}else{return "Invalid Parameter: $Value";}}}// Check if alowed to run in Apacheif ($_SERVER["argc"]==0 & ! $CFG["EnableApache"])return "<b>This Script is configured so that it will not run in Apache.</b>";// Infoprint "Parameters\n";// Correct paths and existenceforeach($CFG as $Key => $Value){if (stripos($Key,"Dir")){// Correct / at the end of pathif (substr($Value,strlen($Value)-1)!="/"){$CFG[$Key]=$Value."/";}// Check existence#print "DIR".$CFG[$Key]."\n";if ( ! is_dir($CFG[$Key])){return "Directory does not exist: ".$Key."=".$CFG[$Key];}}}// Print infoif (count(CFG))foreach($CFG as $Key => $Value)print " $Key=$Value\n";print "\n";// No Errorreturn "";}function SourceAsm($SourceDir, $FileName, &$SourceAsmFiles, &$LabelList )// Process ASM source file, recurse all includes// Returns Error String// Stores file names and labels into two arrays// IN $SourceDir - base directory (not printed)// IN $FileName - file to process// OUT $SourceAsmFiles - list of all processed files (Filename)// OUT $LabelList - list of all labels (Label, FileName, LineNumber){// Startprint "Read Asm: $FileName\n";// Read file$Error=MyReadFile($SourceDir.$FileName, $FileContent);if ($Error!="")return $Error;// Remember filename$SourceAsmFiles[]=$FileName;// Filter source file line by line - find labelsforeach($FileContent as $Key => $Value){// Find label definitionsif (preg_match(LABEL_PATTERN,$Value,$Matches)){print " label @line ".($Key+1)." ".$Matches[1]."\n";$LabelList[]=array("Label"=>$Matches[1],"FileName"=>$FileName,"LineNumber"=>($Key+1));}}// Filter source file line by line - find includesforeach($FileContent as $Key => $Value){// Find .include "filename" linesif (preg_match(INCLUDE_PATTERN,$Value,$Matches)){print " include @line ".($Key+1)." --> ".$Matches[1]."\n";// Remember links$Includes[]=$Matches[1];}}// Print delimiterprint "\n";// Recurse includesif ($Includes){foreach($Includes as $Value){$Dir=dirname($FileName)."/";if ($Dir=="./"){$Dir="";}$Error=SourceAsm($SourceDir, $Dir.$Value, $SourceAsmFiles, $LabelList);if ($Error!="")return $Error;}unset($Includes);}// Endreturn "";}function PrintSourceAsm(&$SourceAsmFiles)// Prints all procesed ASM files{print "Asm Source File List\n";if (count($SourceAsmFiles))foreach($SourceAsmFiles as $Key => $Value){print " ".$Value."\n";}print "\n";}function PrintLabels(&$LabelList)// Prints all found labels{print "Label List\n";if (count($LabelList))foreach($LabelList as $Key => $Value){print " ".$Value["Label"]." ".$Value["FileName"]." ".$Value["LineNumber"]."\n";}print "\n";}function CreateWordList($SourceDir, &$LabelList, &$WordList)// Goes through LabelList and looks for word definitions// Returns Error String// IN $LabelList - Found labels// OUT $WordList - Word List (ShortLabel, Word, Comment, Label, FileName){print "Word List\n";if (count($LabelList))foreach ($LabelList as $Value){// Take all VE definitionsif (stristr(substr($Value["Label"],0,3),"VE_")){// Prepare Label without VE_$ShortLabel=substr($Value["Label"],3);// Prepare search pattern$Pattern=str_replace("Q",$ShortLabel,WORD_PATTERN);#print "Pattern: ".$Pattern." ".$Value["FileName"]."\n";// Read source file$FileName=$SourceDir.$Value["FileName"];$Error=MyReadFileString($FileName, $FileContent);if ($Error!="")return $Error;$FileContent="\n".$FileContent;// Find labelif (preg_match($Pattern,$FileContent,$Matches)){// Coments - remove semiculomn$Comment = rtrim(preg_replace("/\\n; ?(.*)/","$1\n",$Matches[1]));// Convert .db parameters into string$Word="";#$Word=$Matches[2]." : ";foreach(explode(",",$Matches[2]) as $Val){// String elementpreg_match("/^ *\"([^\"]*)(\" *)/",$Val,$Tmp);#print "S:".$Tmp[1]."\n";if ($Tmp[1]!=""){$Word.=$Tmp[1];}// Hexa numberpreg_match("/\\$([0-9A-F]+)/i",$Val,$Tmp);#print "H:".$Tmp[1]."\n";if ($Tmp[1]!=""){$Number=hexdec($Tmp[1]);if ($Number!=0)$Word.=chr($Number);}// Decimal numberpreg_match("/^([0-9]+)/i",$Val,$Tmp);#print "D:".$Tmp[1]."\n";if ($Tmp[1]!=""){$Number=$Tmp[1];if ($Number!=0)$Word.=chr($Number);}}// Store label into array$WordList[]=array("Word"=>$Word, "ShortLabel"=>$ShortLabel, "Comment"=>$Comment,"Label"=>$Value["Label"] , "FileName"=>$Value["FileName"]);print " ".$Word." = ".$ShortLabel."\n";if($Comment) print " ".preg_replace("/\\n/","\n ",$Comment)."\n";}// Sort Wordsarray_multisort($WordList);// Clean Upunset($FileContent);}}print "\n";return "";}function GenerateWordList($TemplateDir, $SvnInfoFileName, $DestinationDir, &$LabelList, &$WordList)// Creates HTML pages with Word List// Returns Error String// IN $TemplateDir - template directory (file WordList.*.html)// IN $LabelList - list of labels (Label, FileName, LineNumber)// IN $WordList - list of words (ShortLabel, Word, Comment, Label, FileName)// OUT WordList.*.html - create HTML pages (file WordList.*.html){// Find all templatesprint "Word List in HTML\n";if (count(glob($TemplateDir."WordList.*.html")))foreach (glob($TemplateDir."WordList.*.html") as $FileName){// Process template fileprint " Temlate $FileName\n";// Read template file$Error=MyReadFileString($FileName, $FileContent);if ($Error!="")return $Error;// Find <<SvnInfo>>if (!preg_match("/( *)(<<SvnInfo>>)/i",$FileContent,$Matches)){unset($FileContent);return "Missing <<SvnInfo>> in template file";}$Indent=$Matches[1];// Read Svn Info file$Error=MyReadFileString($SvnInfoFileName, $SvnInfoFile);if ($Error!=""){// We do not have Svn Info File$SvnInfoFile="";}else{// We have Svn Info File$SvnInfoFile=preg_replace("/^((?:URL|Repository|Last)[^:]*):(.*$)|^.*$/im","<tr><td>$1</td><td>$2</td></tr>",$SvnInfoFile);$SvnInfoFile=preg_replace("~<tr><td></td><td></td></tr>\n~i","",$SvnInfoFile);$SvnInfoFile="<tr><th colspan=\"2\">Subversion Info</th></tr>".$SvnInfoFile;}// Put Svn Info into HTML template$FileContent=str_ireplace("<<SvnInfo>>", $SvnInfoFile, $FileContent);#print $FileContent;// Find <<WordList>>if (!preg_match("/( *)(<<WordList>>)/i",$FileContent,$Matches)){unset($FileContent);return "Missing <<WordList>> in template file";}$Indent=$Matches[1];// Create HTML code - table header$WordListHTML[]="<table>";$WordListHTML[]=" <tr>";$WordListHTML[]=" <th>Word</th>";$WordListHTML[]=" <th>Label</th>";$WordListHTML[]=" <th>Definition</th>";$WordListHTML[]=" </tr>";// Create HTML code - table linesif (count($WordList))foreach($WordList as $Key => $Value){// Prepare (just for readibility)$Word=$Value["Word"];$Link="<a href=\"".ASMFILES.FileName2HTML($Value["FileName"])."#".$Value["ShortLabel"]."\" title=\"".$Value["Label"]."\">".$Value["ShortLabel"]."</a>";$Comment=$Value["Comment"];// Generate HTML$WordListHTML[]=" <tr>";$WordListHTML[]=" <td>".htmlspecialchars($Word)."</td>";$WordListHTML[]=" <td>".$Link."</td>";$WordListHTML[]=" <td>".htmlspecialchars($Comment)."</td>";$WordListHTML[]=" </tr>";}// Create HTML code - table end$WordListHTML[]="</table>";// Indent and Concatenate linesforeach($WordListHTML as $Key => $Value){if ($Key>0)$WordListHTML[$Key]=$Indent.preg_replace("/\n/","<br>",$Value);}$WordListHTML=implode("\n",$WordListHTML);// Put it into HTML template$FileContent=str_ireplace("<<WordList>>", $WordListHTML, $FileContent);#print $FileContent;// Create Output File$Error=MyWriteFile($DestinationDir.basename($FileName), $FileContent);if ($Error!="")return $Error;// Clear memoryunset($FileContent);unset($WordListHTML);}// Delimiterprint "\n";return "";}function GenerateAsmFiles($TemplateDir, $SourceDir, &$SourceAsmFiles, $DestinationDir)// Cretaes HTML files from all processed ASM files// Returns Error String// IN $TemplateDir - directory with template files// IN $SourceDir - directory with asm source files// OUT $SourceAsmFiles -// IN $DestinationDir - directory for generated HTML files{// Infoprint "Copy ASM Files\n";// Destination directory exists$DestinationDir.=ASMFILES;if (!is_dir($DestinationDir))if (!@mkdir($DestinationDir))return "Unable Create Dir ".$DestinationDir;// Read template$Error=MyReadFileString($TemplateDir."FileAsm.en.html", $Template);if ($Error!="")return $Error;// Copy all source filesforeach($SourceAsmFiles as $Key => $FileName){print " ".$FileName."\n";// Read ASM file$Error=MyReadFileString($SourceDir.$FileName, $FileContent);if ($Error!="")return $Error;// Prepare HTML$FileContent=htmlspecialchars($FileContent);$FileContent="<pre>\n".$FileContent."\n</pre>";// Use Template$TemplateWork=$Template;$TemplateWork=str_ireplace("<<FileName>>", $FileName, $TemplateWork);$TemplateWork=str_ireplace("<<FileContent>>", $FileContent, $TemplateWork);// Write ASM file in HTML$Error=MyWriteFile($DestinationDir.FileName2HTML($FileName), $TemplateWork);if ($Error!="")return $Error;}// Delimiterprint "\n";return "";}// **********************************************************************// Main Block// **********************************************************************// Global Like Variables (arrays)// $CFG - Config parameters// $SourceAsmFiles - All processed ASM files (filenames)// $LabelList - All label definitions (Label, FileName, LineNumber)// $WordList - Word List (ShortLabel, Word, Comment, Label, FileName)// Process Command Line ParametersError(Parameters($CFG));// Process all ASM files from the root levelError(SourceAsm($CFG["SourceDir"], $CFG["SourceAsm"], $SourceAsmFiles, $LabelList));PrintSourceAsm($SourceAsmFiles);PrintLabels($LabelList);// Destilate Labels and WordsError(CreateWordList($CFG["SourceDir"], $LabelList, $WordList));// Create HTML WordListError(GenerateWordList($CFG["TemplateDir"],$CFG["SourceDir"].$CFG["SvnInfoFileName"],$CFG["DestinationDir"],$LabelList, $WordList));// Copy ASM files and convert them into HTMLError(GenerateAsmFiles($CFG["TemplateDir"], $CFG["SourceDir"], $SourceAsmFiles, $CFG["DestinationDir"]));// Finishprint "O.K.\n";return// Zpracování readme autora// Vyplatilo by se udělat samostatny formatovaci a nahrazovaci mechanizmus// Zpracování templejtů do samostatného podprogramu (vyřešit indent...)// tím se vyřeší i en/cs verze Asm souboru// Generovat log do souboru místo printu (zvážit) oddělit chyby a varování// Vyčistit cílový adresář// Process all FORTH files// Problém s rekurzí (potenciální nekonečno)// Chtělo by to do stránek vkládat info o verzi a (c)?>