#include "Main.h"
void WebPageParser::ParseLine(const WebPageParameters &PageParameters, const String &Line, ofstream &OutputFile)
{
if(Line.Length() > 0 && Line[0] == '@')
{
PersistentAssert(Line.Length() > 1, "Invalid command");
if(Line[1] == '@')
{
String VariableName, Value;
Line.PartitionAboutIndex(Line.FindFirstIndex('='), VariableName, Value);
VariableName.PopFront();
VariableName.PopFront();
HandleAssignment(VariableName, Value);
}
else
{
String Command, ParameterString;
Line.PartitionAboutIndex(Line.FindFirstIndex('('), Command, ParameterString);
PersistentAssert(ParameterString.Last() == ')', "Invalid command");
ParameterString.PopEnd();
if(Command == "@Include")
{
HandleInclude(PageParameters, ParameterString, OutputFile);
}
else if(Command == "@Code")
{
HandleCode(PageParameters, ParameterString, OutputFile);
}
else
{
SignalError("Invalid command");
}
}
}
else
{
String Result;
SubstituteVariables(Line, Result);
OutputFile << Result << endl;
}
}
WebPageVariable* WebPageParser::GetVariable(const String &Name)
{
for(UINT VariableIndex = 0; VariableIndex < _Variables.Length(); VariableIndex++)
{
if(_Variables[VariableIndex].Name == Name)
{
return &_Variables[VariableIndex];
}
}
return NULL;
}
void WebPageParser::HandleInclude(const WebPageParameters &PageParameters, const String &Filename, ofstream &OutputFile)
{
Vector<String> Lines;
Utility::GetFileLines(PageParameters.SourceDirectory + String("\\") + Filename, Lines);
for(UINT LineIndex = 0; LineIndex < Lines.Length(); LineIndex++)
{
ParseLine(PageParameters, Lines[LineIndex], OutputFile);
}
}
bool WebPageParser::IsCodeFile(const String &Filename)
{
return (Filename.EndsWith(".cpp") || Filename.EndsWith(".h") || Filename.EndsWith(".inl") ||
Filename.EndsWith(".cs") || Filename.EndsWith(".vsh") || Filename.EndsWith(".psh") ||
Filename.EndsWith(".vs") || Filename.EndsWith(".ps"));
}
void WebPageParser::HandleCode(const WebPageParameters &PageParameters, const String &ParameterString, ofstream &OutputFile)
{
String CodeDirectory, OutputDirectory, FullOutputDirectory;
ParameterString.PartitionAboutIndex(ParameterString.FindFirstIndex(','), CodeDirectory, OutputDirectory);
String TempString, CodeFolderName;
OutputDirectory.PartitionAboutIndex(OutputDirectory.FindLastIndex('/'), TempString, CodeFolderName);
OutputFile << "<h4>" << CodeFolderName << " Code Listing</h4><br/>" << endl;
CodeDirectory = CodeDirectory + String("/");
OutputDirectory = OutputDirectory + String("/");
FullOutputDirectory = PageParameters.TargetDirectory + String("/") + OutputDirectory;
Vector<String> AllLines;
UINT TotalLineCount = 0;
Directory BaseCodeDirectory(CodeDirectory);
for(UINT FileIndex = 0; FileIndex < BaseCodeDirectory.Files().Length(); FileIndex++)
{
const String &CurFilename = BaseCodeDirectory.Files()[FileIndex];
if(IsCodeFile(CurFilename))
{
Utility::GetFileLines(CodeDirectory + CurFilename, AllLines);
TotalLineCount += AllLines.Length();
HandleSingleCodeFile(PageParameters, CodeDirectory, CurFilename, FullOutputDirectory + CurFilename, OutputDirectory, 0, OutputFile);
}
}
for(UINT DirectoryIndex = 0; DirectoryIndex < BaseCodeDirectory.Directories().Length(); DirectoryIndex++)
{
const String &SubDirectoryName = BaseCodeDirectory.Directories()[DirectoryIndex];
if(SubDirectoryName != "Debug" && SubDirectoryName != "Release" && SubDirectoryName != "DebugDLL" && SubDirectoryName != "ReleaseDLL" &&
SubDirectoryName != "DebugApp" && SubDirectoryName != "ReleaseApp" && SubDirectoryName != "ipch" &&
SubDirectoryName != "bin" && SubDirectoryName != "obj" && SubDirectoryName != "Properties" && SubDirectoryName != "Icons")
{
Directory SubDirectory(CodeDirectory + SubDirectoryName + String("/"));
OutputFile << "<img height=\"18\" alt=\"x\" src=\"Images/Folder.png\" width=\"20\" border=\"0\"></img>";
OutputFile << "<b>" << SubDirectoryName << "</b><br/>" << endl;
for(UINT FileIndex = 0; FileIndex < SubDirectory.Files().Length(); FileIndex++)
{
const String &CurFilename = SubDirectory.Files()[FileIndex];
if(IsCodeFile(CurFilename))
{
Utility::GetFileLines(SubDirectory.DirectoryPath() + CurFilename, AllLines);
TotalLineCount += AllLines.Length();
HandleSingleCodeFile(PageParameters, SubDirectory.DirectoryPath(), CurFilename, FullOutputDirectory + CurFilename, OutputDirectory, 1, OutputFile);
}
}
}
}
OutputFile << "<p>Total lines of code: <b>" << TotalLineCount << " </b><br/>" << endl;
}
void WebPageParser::HandleSingleCodeFile(const WebPageParameters &PageParameters, const String &CodeDirectory, const String &CodeFilename,
const String &FormattedFile, const String &OutputDirectory, UINT IndentCount, ofstream &OutputFile)
{
const String &RootDirectory = PageParameters.SourceToHTMLConverterDirectory;
if(CopyAllCode && !FormattedFile.Contains("?"))
{
Utility::CopyFile(CodeDirectory + CodeFilename, RootDirectory + String("Temp.txt"));
Utility::CopyFile(CodeDirectory + CodeFilename, FormattedFile);
Console::WriteLine("Converting " + CodeFilename);
Utility::RunCommand(RootDirectory + String("CPPtoHTML.exe"), "Temp.txt", true);
Utility::CopyFile(RootDirectory + String("Temp.txt.html"), FormattedFile + String(".html"));
Vector<String> FileLines;
String FormattedHTMLFilename = FormattedFile + String(".html");
Utility::GetFileLines(FormattedHTMLFilename, FileLines);
ofstream FormattedHTMLFile(FormattedHTMLFilename.CString());
for(UINT LineIndex = 0; LineIndex < FileLines.Length(); LineIndex++)
{
String CurLine = FileLines[LineIndex];
FormattedHTMLFile << CurLine.FindAndReplace("<title>Temp.txt</title>", String("<title>") + CodeFilename + String("</title>")) << endl;
}
}
String ImageName = "Unknown";
if(CodeFilename.EndsWith(".cpp"))
{
ImageName = "Source";
}
else if(CodeFilename.EndsWith(".inl"))
{
ImageName = "Source";
}
else if(CodeFilename.EndsWith(".vsh") || CodeFilename.EndsWith(".vs"))
{
ImageName = "Txt";
}
else if(CodeFilename.EndsWith(".psh") || CodeFilename.EndsWith(".ps"))
{
ImageName = "Txt";
}
else if(CodeFilename.EndsWith(".h"))
{
ImageName = "Header";
}
else if(CodeFilename.EndsWith(".cs"))
{
ImageName = "CSharp";
}
for(UINT IndentIndex = 0; IndentIndex < IndentCount; IndentIndex++)
{
OutputFile << "<img height=\"18\" alt=\"x\" src=\"Images/Placeholder.png\" width=\"20\" border=\"0\"></img>";
}
OutputFile << "<img height=\"18\" alt=\"x\" src=\"Images/" << ImageName << ".png\" width=\"20\" border=\"0\"></img> <a href=\"";
OutputFile << OutputDirectory + CodeFilename << "\">" << CodeFilename << "</a>, <a href=\"" << OutputDirectory + CodeFilename << ".html\">Web Version</a><br/>" << endl;
}
void WebPageParser::HandleAssignment(const String &VariableName, const String &Value)
{
String DereferencedValue;
SubstituteVariables(Value, DereferencedValue);
WebPageVariable* Variable = GetVariable(VariableName);
if(Variable == NULL)
{
_Variables.PushEnd(WebPageVariable(VariableName, DereferencedValue));
}
else
{
Variable->Value = DereferencedValue;
}
}
void WebPageParser::SubstituteVariables(const String &Line, String &Result)
{
Result.FreeMemory();
for(UINT CharIndex = 0; CharIndex < Line.Length(); CharIndex++)
{
char PrevC = ' ';
if(CharIndex != 0)
{
PrevC = Line[CharIndex - 1];
}
char C = Line[CharIndex];
if(PrevC == ' ' && C == '@')
{
String VariableName;
bool Done = false;
for(CharIndex = CharIndex + 1; CharIndex < Line.Length() && !Done; CharIndex++)
{
C = Line[CharIndex];
if(isalpha(C))
{
VariableName.PushEnd(C);
}
else
{
CharIndex--;
Done = true;
}
}
CharIndex--;
WebPageVariable* Variable = GetVariable(VariableName);
PersistentAssert(Variable != NULL, String("Variable ") + VariableName + String(" not found"));
Result += Variable->Value;
}
else
{
Result.PushEnd(C);
}
}
}