{HEADER END}
{FILE START}

MLAB

[/] [Articles/] [Forth/] [PHP/] [GenerateHTML.php] - Revize 545

Přejdi na současnou revizi

Porovnej s předchozí - Blame - Stáhnout jako soubor

<?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 Word
define ('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 content
  
if ($FileContent==FALSE)
    return 
"No Data in File: $FileName";

  
// Remove CR or LF or CR/LF
  
foreach($FileContent as $Key => $Line)
  {
    
$FileContent[$Key]=rtrim($Line);
  }

  
// No error
  
return "";
}


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 string
  
if ($Error==""$FileContent=implode("\n",$FileContent);

  
// Finished
  
return $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 content
    
fwrite($File,$FileContent);
    
fclose($File);
    
    
// No Error
    
return "";
}


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 $LabelList
  
foreach($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 
"  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
{
  
// Info
  
print "Parameters\n";
  
// Dummy values
  
$CFG["EnableApache"]    =  0;     // Do not allow run in Apache
  
$CFG["SourceDir"]       = "";
  
$CFG["SourceAsm"]       = "";
  
$CFG["TemplateDir"]     = "";
  
$CFG["DestinationDir"]  = "";
  
// Default values (in cfg file)
  
@include_once("GenerateHTML.cfg");
  
// Command Line parameters
  
if ($_SERVER["argc"]>1)
  {
    
// Help
    
if ($_SERVER["argv"][1]=="--help")
      
Help();
    
// Drop
    
unset($_SERVER["argv"][0]);
    
// Go through arguments
    
foreach($_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";
      }
    }
  }

  
// Correct paths and existence
  
foreach($CFG as $Key => $Value)
  {
    if (
stripos($Key,"Dir"))
    {
      
// Correct / at the end of path
      
if (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 info
  
if (count(CFG))
  foreach(
$CFG as $Key => $Value)
    print 
"  $Key=$Value\n";
  print 
"\n";

  
// Check if alowed to run in Apache
  
if ($_SERVER["argc"]==& ! $CFG["Apache"])
    return 
"This Script is configured so that it will not run in Apache.";

  
// No Error
  
return "";
}


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)
{

  
// Start
  
print "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 labels
  
foreach($FileContent as $Key => $Value)
  {
    
// Find label definitions
    
if (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 includes
  
foreach($FileContent as $Key => $Value)
  {
    
// Find .include "filename" lines
    
if (preg_match(INCLUDE_PATTERN,$Value,$Matches))
    {
      print 
"  include @line ".($Key+1)." --> ".$Matches[1]."\n";
      
// Remember links
      
$Includes[]=$Matches[1];
    }
  }

  
// Print delimiter
  
print "\n";
  
  
// Recurse includes
  
if ($Includes)
  {
    foreach(
$Includes as $Value)
    {
      
$Dir=dirname($FileName)."/";
      if (
$Dir=="./")
      {
        
$Dir="";
      }
      
$Error=SourceAsm($SourceDir$Dir.$Value$SourceAsmFiles$LabelList);
      if (
$Error!="")
        return 
$Error;
    }
    unset(
$Includes);
  }

  
// End
  
return "";
}


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 definitions
    
if (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 label
      
if (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 element
          
preg_match("/^ *\"([^\"]*)(\" *)/",$Val,$Tmp);
          
#print "S:".$Tmp[1]."\n";
          
if ($Tmp[1]!="")
          {
            
$Word.=$Tmp[1];
          }

          
// Hexa number
          
preg_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 number
          
preg_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 Words
      
array_multisort($WordList);

      
// Clean Up
      
unset($FileContent);
    }
  }
  print 
"\n";
  return 
"";
}


function 
GenerateWordList($TemplateDir$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 templates
  
print "Word List in HTML\n";
  if (
count(glob($TemplateDir."WordList.*.html")))
  foreach (
glob($TemplateDir."WordList.*.html") as $FileName)
  {
    
// Process template file
    
print "  Temlate $FileName\n";

    
// Read template file
    
$Error=MyReadFileString($FileName$FileContent);
    if (
$Error!="")
      return 
$Error;

    
// 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 lines
    
if (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 lines
    
foreach($WordListHTML as $Key => $Value)
    {
      
$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 memory
    
unset($FileContent);
    unset(
$WordListHTML);
  }

  
// Delimiter
  
print "\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
{
  
// Info
  
print "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 files
  
foreach($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;
  }
  
  
// Delimiter
  
print "\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 Parameters
Error(Parameters($CFG));

// Process all ASM files from the root level
Error(SourceAsm($CFG["SourceDir"], $CFG["SourceAsm"], $SourceAsmFiles$LabelList));
PrintSourceAsm($SourceAsmFiles);
PrintLabels($LabelList);

// Destilate Labels and Words
Error(CreateWordList($CFG["SourceDir"], $LabelList$WordList));

// Create HTML WordList
Error(GenerateWordList($CFG["TemplateDir"], $CFG["DestinationDir"], $LabelList$WordList));

// Copy ASM files and convert them into HTML
Error(GenerateAsmFiles($CFG["TemplateDir"], $CFG["SourceDir"], $SourceAsmFiles$CFG["DestinationDir"]));

// Finish
print "O.K.\n";
return

// Zpracování readme autora + verze
// 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)
?>
{FILE END}
{FOOTER START}

Poháněno WebSVN v2.1 alpha 1