markers[MarkerIndex].type == HMML_CATEGORY)
{
- GenerateTopicColours(Anno->markers[MarkerIndex].marker, Config.CSSDir);
+ switch(GenerateTopicColours(Anno->markers[MarkerIndex].marker, Config.CSSDir))
+ {
+ case RC_SUCCESS:
+ case RC_NOOP:
+ break;
+ case RC_ERROR_FILE:
+ case RC_ERROR_MEMORY:
+ return RC_ERROR_FATAL;
+ };
if(!HasFilterMenu)
{
HasFilterMenu = TRUE;
@@ -1716,14 +1875,14 @@ HMMLToBuffers(buffer *MemoryArena, buffers *CollationBuffers, config Config, cha
if(BuildReference(ReferencesArray, RefIdentifier, UniqueRefs, *CurrentRef, *Anno) == 1)
{
+ LogError(Config, LOG_ERROR, "Reference combination processing failed: %s:%d", Filename, Anno->line);
fprintf(stderr, "%s:%d: Cannot process new combination of reference info\n"
"\n"
"Either tweak your annotation, or contact matt@handmadedev.org\n"
"mentioning the ref node you want to write and how you want it to\n"
"appear in the references menu\n", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena->Location);
- return 1;
+ return RC_INVALID_REFERENCE;
}
++ReferencesArray[RefIdentifier - 1].IdentifierCount;
++UniqueRefs;
@@ -1736,10 +1895,10 @@ HMMLToBuffers(buffer *MemoryArena, buffers *CollationBuffers, config Config, cha
{
if(ReferencesArray[i].IdentifierCount == REF_MAX_IDENTIFIER)
{
+ LogError(Config, LOG_EMERGENCY, "REF_MAX_IDENTIFIER (%d) reached. Contact matt@handmadedev.org", REF_MAX_IDENTIFIER);
fprintf(stderr, "%s:%d: Too many timecodes associated with one reference (increase REF_MAX_IDENTIFIER)\n", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_ERROR_MAX_REFS;
}
if(CurrentRef->isbn)
{
@@ -1763,23 +1922,23 @@ HMMLToBuffers(buffer *MemoryArena, buffers *CollationBuffers, config Config, cha
}
else
{
+ LogError(Config, LOG_ERROR, "Reference missing ISBN or URL: %s:%d", Filename, Anno->line);
fprintf(stderr, "%s:%d: Reference must have an ISBN or URL\n", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_INVALID_REFERENCE;
}
}
if(BuildReference(ReferencesArray, RefIdentifier, UniqueRefs, *CurrentRef, *Anno) == 1)
{
+ LogError(Config, LOG_ERROR, "Reference combination processing failed: %s:%d", Filename, Anno->line);
fprintf(stderr, "%s:%d: Cannot process new combination of reference info\n"
"\n"
"Either tweak your annotation, or contact matt@handmadedev.org\n"
"mentioning the ref node you want to write and how you want it to\n"
"appear in the references menu\n", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_INVALID_REFERENCE;
}
++ReferencesArray[UniqueRefs].IdentifierCount;
++UniqueRefs;
@@ -1797,10 +1956,10 @@ AppendedIdentifier:
}
else
{
+ LogError(Config, LOG_ERROR, "Reference missing ISBN or URL: %s:%d", Filename, Anno->line);
fprintf(stderr, "%s:%d: Reference must have an ISBN or URL\n", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_INVALID_REFERENCE;
}
HasReference = TRUE;
@@ -1817,10 +1976,10 @@ AppendedIdentifier:
}
else
{
+ LogError(Config, LOG_ERROR, "Reference missing ISBN or URL: %s:%d", Filename, Anno->line);
fprintf(stderr, "%s:%d: Reference must have an ISBN or URL", Filename, Anno->line);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_INVALID_REFERENCE;
}
}
@@ -1899,14 +2058,14 @@ AppendedIdentifier:
Anno->quote.id,
Config.CacheDir) == 1)
{
- fprintf(stderr, "%s:%d: Quote #%s %d not found. Unlucky!\n",
+ LogError(Config, LOG_ERROR, "Quote #%s %d not found: %s:%d", Speaker, Anno->quote.id, Filename, Anno->line);
+ fprintf(stderr, "%s:%d: Quote #%s %d not found. Skipping this file...\n",
Filename,
Anno->line,
Speaker,
Anno->quote.id);
hmml_free(&HMML);
- //free(MemoryArena.Location);
- return 1;
+ return RC_ERROR_QUOTE;
}
CopyStringToBuffer(&QuoteMenu,
@@ -1947,7 +2106,15 @@ AppendedIdentifier:
while(MarkerIndex < Anno->marker_count)
{
- GenerateTopicColours(Anno->markers[MarkerIndex].marker, Config.CSSDir);
+ switch(GenerateTopicColours(Anno->markers[MarkerIndex].marker, Config.CSSDir))
+ {
+ case RC_SUCCESS:
+ case RC_NOOP:
+ break;
+ case RC_ERROR_FILE:
+ case RC_ERROR_MEMORY:
+ return RC_ERROR_FATAL;
+ };
if(!HasFilterMenu)
{
HasFilterMenu = TRUE;
@@ -2463,7 +2630,10 @@ AppendedIdentifier:
CopyStringToBuffer(&CollationBuffers->IncludesIndex,
"
\n"
"
\n"
- "
\n",
+ "
\n"
+ "\n"
+ "
\n"
+ "
\n",
Config.CSSDir,
Config.CSSDir,
HMML.metadata.project,
@@ -2747,166 +2917,155 @@ Cleanup:
}
else
{
+ LogError(Config, LOG_ERROR, "%s:%d: %s", Filename, HMML.error.line, HMML.error.message);
fprintf(stderr, "%s:%d: %s\n", Filename, HMML.error.line, HMML.error.message);
+ hmml_free(&HMML);
+ return RC_ERROR_HMML;
}
hmml_free(&HMML);
- return 0;
+ return RC_SUCCESS;
}
-void
-BuffersToHTML(buffer *MemoryArena, buffers CollationBuffers, buffer Template, config Config, char *OutputPath)
+int
+BuffersToHTML(arena *MemoryArena, buffers CollationBuffers, template *TemplateMetadata, config Config, char *OutputPath, int PageType)
{
- buffer Master;
- ClaimBuffer(MemoryArena, &Master, "Master", Kilobytes(512));
#if DEBUG
- printf("\n\n --- Buffer Collation ---\n\n\n\n");
+ printf("\n\n --- Buffer Collation ---\n"
+ " %s\n\n\n", OutputPath);
#endif
if(Config.Mode == MODE_INTEGRATE)
{
- buffer Output;
- Output.Size = Template.Size + Master.Size;
- Output.ID = "Output";
- if(!(Output.Location = malloc(Output.Size)))
+ if(TemplateMetadata->Validity & PageType)
{
- // TODO(matt): Error code
- //perror(Args[0]); free(Template.Location); hmml_free(&HMML); free(MemoryArena.Location); return 1;
- }
- Output.Ptr = Output.Location;
-
- char *IncludesTag = "__CINERA_INCLUDES__";
- char *TitleTag = "__CINERA_TITLE__";
- char *MenusTag = "__CINERA_MENUS__";
- char *PlayerTag = "__CINERA_PLAYER__";
- char *ScriptTag = "__CINERA_SCRIPT__";
-
- while(Template.Ptr - Template.Location < Template.Size)
- {
- if(*Template.Ptr == '!' && (Template.Ptr > Template.Location && !StringsDifferT("", Template.Ptr, 0))
- {
- Template.Ptr += StringLength("-->");
- break;
- }
- ++Template.Ptr;
- }
- break;
- }
-
- else if(!(StringsDifferT(TitleTag, Template.Ptr, 0)))
- {
- Output.Ptr = CommentStart;
- CopyStringToBuffer(&Output, CollationBuffers.Title);
- while(Template.Ptr - Template.Location < Template.Size)
- {
- if(!StringsDifferT("-->", Template.Ptr, 0))
- {
- Template.Ptr += StringLength("-->");
- break;
- }
- ++Template.Ptr;
- }
- break;
- }
- else if(!(StringsDifferT(MenusTag, Template.Ptr, 0)))
- {
- Output.Ptr = CommentStart;
- CopyBuffer(&Output, &CollationBuffers.Menus);
- while(Template.Ptr - Template.Location < Template.Size)
- {
- if(!StringsDifferT("-->", Template.Ptr, 0))
- {
- Template.Ptr += StringLength("-->");
- break;
- }
- ++Template.Ptr;
- }
- break;
- }
- else if(!(StringsDifferT(PlayerTag, Template.Ptr, 0)))
- {
- Output.Ptr = CommentStart;
- CopyBuffer(&Output, &CollationBuffers.Player);
- while(Template.Ptr - Template.Location < Template.Size)
- {
- if(!StringsDifferT("-->", Template.Ptr, 0))
- {
- Template.Ptr += StringLength("-->");
- break;
- }
- ++Template.Ptr;
- }
- break;
- }
- else if(!(StringsDifferT(ScriptTag, Template.Ptr, 0)))
- {
- Output.Ptr = CommentStart;
- CopyBuffer(&Output, &CollationBuffers.Script);
- while(Template.Ptr - Template.Location < Template.Size)
- {
- if(!StringsDifferT("-->", Template.Ptr, 0))
- {
- Template.Ptr += StringLength("-->");
- break;
- }
- ++Template.Ptr;
- }
- break;
- }
- else if(!StringsDifferT("-->", Template.Ptr, 0))
- {
- break;
- }
- *Output.Ptr++ = *Template.Ptr++;
- }
+ LogError(Config, LOG_ERROR, "Unable to open template %s: %s", TemplateMetadata->Filename, strerror(errno));
+ return RC_ERROR_FILE;
}
- else
+ fseek(TemplateFile, 0, SEEK_END);
+ Template.Size = ftell(TemplateFile);
+ fseek(TemplateFile, 0, SEEK_SET);
+ if(!(Template.Location = malloc(Template.Size)))
+ {
+ LogError(Config, LOG_ERROR, "BuffersToHTML(): %s",
+ strerror(errno));
+ fclose(TemplateFile);
+ return RC_ERROR_MEMORY;
+ }
+ Template.Ptr = Template.Location;
+ fread(Template.Location, Template.Size, 1, TemplateFile);
+ fclose(TemplateFile);
+
+ buffer Output;
+ Output.Size = Template.Size + (Kilobytes(512));
+ Output.ID = "Output";
+ if(!(Output.Location = malloc(Output.Size)))
+ {
+ LogError(Config, LOG_ERROR, "BuffersToHTML(): %s",
+ strerror(errno));
+ FreeBuffer(&Template);
+ return RC_ERROR_MEMORY;
+ }
+ Output.Ptr = Output.Location;
+
+ Template.Ptr = Template.Location;
+ for(int i = 0; i < TemplateMetadata->TagCount; ++i)
+ {
+ int j = 0;
+ while(TemplateMetadata->Tag[i].Offset > j)
+ {
+ *Output.Ptr++ = *Template.Ptr++;
+ ++j;
+ }
+
+ switch(TemplateMetadata->Tag[i].TagCode)
+ {
+ case TAG_TITLE:
+ CopyStringToBuffer(&Output, CollationBuffers.Title);
+ break;
+ case TAG_INDEX:
+ CopyBuffer(&Output, &CollationBuffers.Index);
+ break;
+ case TAG_INCLUDES:
+ if(PageType == PAGE_PLAYER)
+ {
+ CopyBuffer(&Output, &CollationBuffers.IncludesPlayer);
+ }
+ else
+ {
+ CopyBuffer(&Output, &CollationBuffers.IncludesIndex);
+ }
+ break;
+ case TAG_MENUS:
+ CopyBuffer(&Output, &CollationBuffers.Menus);
+ break;
+ case TAG_PLAYER:
+ CopyBuffer(&Output, &CollationBuffers.Player);
+ break;
+ case TAG_SCRIPT:
+ CopyBuffer(&Output, &CollationBuffers.Script);
+ break;
+ }
+ DepartComment(&Template);
+ }
+ while(Template.Ptr - Template.Location < Template.Size)
{
*Output.Ptr++ = *Template.Ptr++;
}
- }
- FILE *OutFile;
- if(!(OutFile = fopen(Config.Edition == EDITION_PROJECT ? OutputPath : Config.OutIntegratedLocation, "w")))
+ FreeBuffer(&Template);
+
+ FILE *OutFile;
+ if(!(OutFile = fopen(Config.Edition == EDITION_PROJECT ? OutputPath : Config.OutIntegratedLocation, "w")))
+ {
+ LogError(Config, LOG_ERROR, "Unable to open output file %s: %s", Config.Edition == EDITION_PROJECT ? OutputPath : Config.OutIntegratedLocation, strerror(errno));
+ free(Output.Location);
+ return RC_ERROR_FILE;
+ }
+ fwrite(Output.Location, Output.Ptr - Output.Location, 1, OutFile);
+ fclose(OutFile);
+
+ free(Output.Location);
+ return RC_SUCCESS;
+ }
+ else
{
- // TODO(matt): Return code
- //perror(Config.OutIntegratedLocation); free(Template.Location); free(Output.Location); hmml_free(&HMML); free(MemoryArena.Location); return 1;
+ return RC_INVALID_TEMPLATE;
}
- fwrite(Output.Location, Output.Ptr - Output.Location, 1, OutFile);
- fclose(OutFile);
-
- free(Output.Location);
}
else
{
- // NOTE(matt): Perform the normal collation into Master, and write-out to out.html
+ buffer Master;
+ if(ClaimBuffer(MemoryArena, &Master, "Master", Kilobytes(512)) == RC_ARENA_FULL) { return RC_ARENA_FULL; };
+
CopyStringToBuffer(&Master,
"\n"
" \n");
- //NOTE(matt): Here is where we do all our CopyBuffer() calls
- CopyBuffer(&Master, &CollationBuffers.IncludesPlayer);
+ CopyBuffer(&Master, PageType == PAGE_PLAYER ? &CollationBuffers.IncludesPlayer : &CollationBuffers.IncludesIndex);
+ CopyStringToBuffer(&Master, "\n");
+
CopyStringToBuffer(&Master,
- "\n"
" \n"
" \n");
- CopyBuffer(&Master, &CollationBuffers.Menus);
- CopyStringToBuffer(&Master, "\n");
- CopyBuffer(&Master, &CollationBuffers.Player);
- CopyStringToBuffer(&Master, "\n");
- CopyBuffer(&Master, &CollationBuffers.Script);
- CopyStringToBuffer(&Master, "\n");
- //
+ if(PageType == PAGE_PLAYER)
+ {
+ CopyBuffer(&Master, &CollationBuffers.Menus);
+ CopyStringToBuffer(&Master, "\n");
+ CopyBuffer(&Master, &CollationBuffers.Player);
+ CopyStringToBuffer(&Master, "\n");
+ CopyBuffer(&Master, &CollationBuffers.Script);
+ CopyStringToBuffer(&Master, "\n");
+ }
+ else
+ {
+ CopyBuffer(&Master, &CollationBuffers.Index);
+ }
CopyStringToBuffer(&Master,
" \n"
@@ -2915,45 +3074,49 @@ BuffersToHTML(buffer *MemoryArena, buffers CollationBuffers, buffer Template, co
FILE *OutFile;
if(!(OutFile = fopen(Config.Edition == EDITION_PROJECT ? OutputPath : Config.OutLocation, "w")))
{
- // TODO(matt): Error code
- //perror(OutLocation); hmml_free(&HMML); free(MemoryArena.Location); return 1;
+ LogError(Config, LOG_ERROR, "Unable to open output file %s: %s", Config.Edition == EDITION_PROJECT ? OutputPath : Config.OutLocation, strerror(errno));
+ DeclaimBuffer(MemoryArena, &Master);
+ return RC_ERROR_FILE;
}
fwrite(Master.Location, Master.Ptr - Master.Location, 1, OutFile);
fclose(OutFile);
+ DeclaimBuffer(MemoryArena, &Master);
+ return RC_SUCCESS;
}
-
- DeclaimBuffer(MemoryArena, &Master);
}
int
-BuildIndex(buffer *MemoryArena, buffers *CollationBuffers, config Config, char *BaseFilename, char *Title)
+RefreshIndex(arena *MemoryArena, buffers *CollationBuffers, config Config, char *BaseFilename)
{
char IndexPath[255];
- CopyString(IndexPath, "%s/index", Config.CacheDir);
+ CopyString(IndexPath, "%s/%s.index", Config.CacheDir, CollationBuffers->Project);
FILE *IndexFile;
if(!(IndexFile = fopen(IndexPath, "a+")))
{
- perror(IndexPath);
- // TODO(matt): Actual error code
- return 1;
+ LogError(Config, LOG_ERROR, "Unable to open index file %s: %s", IndexPath, strerror(errno));
+ return RC_ERROR_FILE;
}
buffer Index;
+ Index.ID = "Index";
fseek(IndexFile, 0, SEEK_END);
- Index.Size = ftell(IndexFile);
+ int IndexFileSize = ftell(IndexFile);
+ Index.Size = IndexFileSize + StringLength(BaseFilename) + StringLength(CollationBuffers->Title) + 3;
fseek(IndexFile, 0, SEEK_SET);
if(!(Index.Location = malloc(Index.Size)))
{
- perror("BuildIndex");
+ LogError(Config, LOG_ERROR, "RefreshIndex(): %s", strerror(errno));
+ return RC_ERROR_MEMORY;
}
Index.Ptr = Index.Location;
- fread(Index.Location, Index.Size, 1, IndexFile);
+ fread(Index.Location, IndexFileSize, 1, IndexFile);
bool Found = FALSE;
+ bool Inserted = FALSE;
int EntryCount = 0;
- while(Index.Ptr - Index.Location < Index.Size)
+ while(Index.Ptr - Index.Location < IndexFileSize)
{
char IndexedFile[32];
char *Ptr = IndexedFile;
@@ -2963,86 +3126,208 @@ BuildIndex(buffer *MemoryArena, buffers *CollationBuffers, config Config, char *
Found = TRUE;
break;
}
+ else if(StringsDiffer(IndexedFile, BaseFilename) > 0)
+ {
+ while(Index.Ptr > Index.Location && *Index.Ptr != '\n')
+ {
+ --Index.Ptr;
+ }
+ if(Index.Ptr > Index.Location)
+ {
+ ++Index.Ptr;
+ }
+
+ int Head = Index.Ptr - Index.Location;
+ buffer Scratch;
+ Scratch.Size = IndexFileSize;
+ if(!(Scratch.Location = malloc(Scratch.Size + 1)))
+ {
+ LogError(Config, LOG_ERROR, "RefreshIndex(): %s", strerror(errno));
+ free(Index.Location);
+ return RC_ERROR_MEMORY;
+ }
+ Scratch.Ptr = Scratch.Location;
+ while(Index.Ptr - Index.Location < IndexFileSize)
+ {
+ *Scratch.Ptr++ = *Index.Ptr++;
+ }
+ *Scratch.Ptr = '\0';
+
+ Index.Ptr = Index.Location + Head;
+ CopyStringToBuffer(&Index, "%s,%s\n", BaseFilename, CollationBuffers->Title);
+
+ CopyStringToBuffer(&Index, Scratch.Location);
+ free(Scratch.Location);
+
+ fclose(IndexFile);
+ IndexFile = fopen(IndexPath, "w");
+ fwrite(Index.Location, Index.Ptr - Index.Location, 1, IndexFile);
+
+ Inserted = TRUE;
+ }
else
{
- while(Index.Ptr - Index.Location < Index.Size && *Index.Ptr != '\n')
+ while(Index.Ptr - Index.Location < IndexFileSize && *Index.Ptr != '\n')
{
++Index.Ptr;
}
++Index.Ptr;
- ++EntryCount;
}
+ ++EntryCount;
}
if(Found == FALSE)
{
++EntryCount;
// TODO(matt): Write the EntryCount into the index
- fprintf(IndexFile, "%s,%s\n", BaseFilename, Title);
+ if(Inserted == FALSE)
{
- char IndexPagePath[255];
- CopyString(IndexPagePath, "%s/index.html", Config.BaseDir);
- CollationBuffers->Index.Ptr = CollationBuffers->Index.Location;
- CopyStringToBuffer(&CollationBuffers->Index, "
\n");
- Index.Ptr = Index.Location;
- while(Index.Ptr - Index.Location < Index.Size)
- {
- char IndexedFile[32];
- char *Ptr = IndexedFile;
- Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, ',') + 1;
+ fprintf(IndexFile, "%s,%s\n", BaseFilename, CollationBuffers->Title);
+ }
- char Title[255];
- Ptr = Title;
- Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, '\n') + 1;
+ RewindBuffer(&CollationBuffers->Index);
+ CopyStringToBuffer(&CollationBuffers->Index, "\n");
+ Index.Ptr = Index.Location;
+ while(Index.Ptr - Index.Location < IndexFileSize)
+ {
+ char IndexedFile[32];
+ char *Ptr = IndexedFile;
+ Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, ',') + 1;
- CopyStringToBuffer(&CollationBuffers->Index,
+ char Title[255];
+ Ptr = Title;
+ Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, '\n') + 1;
+
+ CopyStringToBuffer(&CollationBuffers->Index,
" - \n"
" %s\n"
"
\n",
-IndexedFile, Title);
+ IndexedFile, Title);
- }
- CopyStringToBuffer(&CollationBuffers->Index, "
\n");
-
- if(Config.Mode == MODE_INTEGRATE)
- {
- }
- else
- {
- }
-
- buffer Master;
- ClaimBuffer(MemoryArena, &Master, "Master", Kilobytes(16));
- CopyStringToBuffer(&Master,
- "\n"
- " \n");
- CopyBuffer(&Master, &CollationBuffers->IncludesIndex);
-
- CopyStringToBuffer(&Master,
- "\n"
- " \n"
- " \n");
- CopyBuffer(&Master, &CollationBuffers->Index);
- CopyStringToBuffer(&Master,
- "\n"
- " \n"
- "\n");
-
- FILE *ContentsPage;
- if(!(ContentsPage = fopen(IndexPagePath, "w")))
- {
- perror(IndexPagePath);
- }
- fwrite(Master.Location, Master.Ptr - Master.Location, 1, ContentsPage);
- fclose(ContentsPage);
-
- DeclaimBuffer(MemoryArena, &Master);
}
+ CopyStringToBuffer(&CollationBuffers->Index, "
");
}
fclose(IndexFile);
FreeBuffer(&Index);
- return 0;
+ return Found ? RC_NOOP : RC_REFRESHED;
+}
+
+int
+RefreshProject(arena *MemoryArena, buffers *CollationBuffers,
+ template *IndexTemplateMetadata, template *PlayerTemplateMetadata,
+ config Config)
+{
+ DIR *ProjectDirHandle;
+ if(!(ProjectDirHandle = opendir(Config.ProjectDir)))
+ {
+ LogError(Config, LOG_ERROR, "Unable to scan project directory %s: %s", Config.ProjectDir, strerror(errno));
+ fprintf(stderr, "Unable to scan project directory %s: %s\n", Config.ProjectDir, strerror(errno));
+ return RC_ERROR_DIRECTORY;
+ }
+
+ struct dirent *ProjectFiles;
+ int FileIndex = 0;
+
+NextFile:
+ while((ProjectFiles = readdir(ProjectDirHandle)))
+ {
+ // TODO(matt): Loft out into a function, maybe?
+ char *Ptr;
+ Ptr = ProjectFiles->d_name;
+ Ptr += (StringLength(ProjectFiles->d_name) - StringLength(".hmml"));
+ if(!(StringsDiffer(Ptr, ".hmml")))
+ {
+ *Ptr = '\0';
+ char BaseFilename[255];
+ CopyString(BaseFilename, ProjectFiles->d_name);
+ *Ptr = '.';
+
+ switch(HMMLToBuffers(MemoryArena, CollationBuffers, Config, ProjectFiles->d_name))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_ERROR_FILE:
+ case RC_ERROR_FATAL:
+ closedir(ProjectDirHandle);
+ return RC_ERROR_FATAL;
+ case RC_ERROR_HMML:
+ case RC_ERROR_MAX_REFS:
+ case RC_ERROR_QUOTE:
+ case RC_INVALID_REFERENCE:
+ goto NextFile;
+ case RC_SUCCESS:
+ break;
+ };
+
+ switch(RefreshIndex(MemoryArena, CollationBuffers, Config, BaseFilename))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_ERROR_FILE:
+ case RC_ERROR_MEMORY:
+ closedir(ProjectDirHandle);
+ return RC_ERROR_FATAL;
+ case RC_NOOP:
+ break;
+ case RC_REFRESHED:
+ {
+ char OutputDir[255];
+ CopyString(OutputDir, "%s/%s", Config.BaseDir, BaseFilename);
+ char OutputPath[255];
+ CopyString(OutputPath, "%s/index.html", OutputDir);
+ DIR *OutputDirectoryHandle;
+ if(!(OutputDirectoryHandle = opendir(OutputDir)))
+ {
+ if(MakeDir(OutputDir) == RC_ERROR_DIRECTORY)
+ {
+ LogError(Config, LOG_ERROR, "Unable to create directory %s: %s", OutputDir, strerror(errno));
+ fprintf(stderr, "Unable to create directory %s: %s\n", OutputDir, strerror(errno));
+ closedir(ProjectDirHandle);
+ return RC_ERROR_DIRECTORY;
+ };
+ }
+ closedir(OutputDirectoryHandle);
+ // TODO(matt): Implement checksumming?
+
+ char IndexPagePath[255];
+ CopyString(IndexPagePath, "%s/index.html", Config.BaseDir);
+ switch(BuffersToHTML(MemoryArena, *CollationBuffers, IndexTemplateMetadata, Config, IndexPagePath, PAGE_INDEX))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_INVALID_TEMPLATE:
+ LogError(Config, LOG_ERROR, "Invalid index template: %s", IndexTemplateMetadata->Filename);
+ fprintf(stderr, "Invalid index template: %s\n", IndexTemplateMetadata->Filename);
+ closedir(ProjectDirHandle);
+ case RC_ERROR_MEMORY:
+ case RC_ERROR_FILE:
+ case RC_ARENA_FULL:
+ return RC_ERROR_FATAL;
+ case RC_SUCCESS:
+ break;
+ }
+
+ switch(BuffersToHTML(MemoryArena, *CollationBuffers, PlayerTemplateMetadata, Config, OutputPath, PAGE_PLAYER))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_INVALID_TEMPLATE:
+ LogError(Config, LOG_ERROR, "Invalid player template: %s", PlayerTemplateMetadata->Filename);
+ fprintf(stderr, "Invalid player template: %s\n", PlayerTemplateMetadata->Filename);
+ closedir(ProjectDirHandle);
+ case RC_ERROR_MEMORY:
+ case RC_ERROR_FILE:
+ case RC_ARENA_FULL:
+ return RC_ERROR_FATAL;
+ case RC_SUCCESS:
+ break;
+ }
+ }
+ break;
+ }
+
+ ++FileIndex;
+ }
+ }
+ closedir(ProjectDirHandle);
+ return RC_SUCCESS;
}
int
@@ -3055,13 +3340,15 @@ main(int ArgC, char **Args)
.Edition = EDITION_SINGLE,
.ImagesDir = ".",
.JSDir = ".",
+ .LogLevel = LOG_DEBUG,
.DefaultMedium = "programming",
.Mode = getenv("CINERA_MODE") ? MODE_INTEGRATE : MODE_BARE,
.OutLocation = "out.html",
.OutIntegratedLocation = "out_integrated.html",
.ForceIntegration = FALSE,
.ProjectDir = ".",
- .TemplateLocation = "template.html"
+ .TemplatePlayerLocation = "template_player.html",
+ .TemplateIndexLocation = "template_index.html"
};
if(getenv("XDG_CACHE_HOME"))
@@ -3078,11 +3365,11 @@ main(int ArgC, char **Args)
if(ArgC < 2)
{
PrintUsage(Args[0], DefaultConfig);
- return 1;
+ return RC_RIP;
}
char CommandLineArg;
- while((CommandLineArg = getopt(ArgC, Args, "b:c:fi:j:m:o:p:q:t:h")) != -1)
+ while((CommandLineArg = getopt(ArgC, Args, "b:c:fi:j:l:m:o:p:q:t:x:h")) != -1)
{
switch(CommandLineArg)
{
@@ -3101,6 +3388,10 @@ main(int ArgC, char **Args)
case 'j':
Config.JSDir = optarg;
break;
+ case 'l':
+ // TODO(matt): Make this actually take a string, rather than requiring the LogLevel number
+ Config.LogLevel = StringToInt(optarg);
+ break;
case 'm':
Config.DefaultMedium = optarg;
break;
@@ -3112,7 +3403,11 @@ main(int ArgC, char **Args)
Config.ProjectDir = optarg;
break;
case 't':
- Config.TemplateLocation = optarg;
+ Config.TemplatePlayerLocation = optarg;
+ Config.Mode = MODE_INTEGRATE;
+ break;
+ case 'x':
+ Config.TemplateIndexLocation = optarg;
Config.Mode = MODE_INTEGRATE;
break;
//case 'c':
@@ -3180,18 +3475,19 @@ main(int ArgC, char **Args)
// And, in that same state, we gotta keep a Template buffer around
// NOTE(matt): Init MemoryArena
- buffer MemoryArena;
+ arena MemoryArena;
MemoryArena.Size = Megabytes(4);
if(!(MemoryArena.Location = calloc(MemoryArena.Size, 1)))
{
- perror(Args[0]);
- //free(Template.Location);
- return 1;
+ LogError(Config, LOG_EMERGENCY, "%s: %s", Args[0], strerror(errno));
+ return RC_RIP;
}
MemoryArena.Ptr = MemoryArena.Location;
+ buffer Errors;
+ if(ClaimBuffer(&MemoryArena, &Errors, "Errors", Kilobytes(1)) == RC_ARENA_FULL) { goto RIP; };
+
// NOTE(matt): Setup buffers and ptrs
- // TODO(matt)
//char *InPtr;
// NOTE(matt): Tree structure of buffer dependencies
@@ -3200,24 +3496,45 @@ main(int ArgC, char **Args)
// Player
// Script
- // TODO(matt)
-#if 1
buffers CollationBuffers;
- ClaimBuffer(&MemoryArena, &CollationBuffers.IncludesPlayer, "IncludesPlayer", Kilobytes(1));
- ClaimBuffer(&MemoryArena, &CollationBuffers.Menus, "Menus", Kilobytes(24));
- ClaimBuffer(&MemoryArena, &CollationBuffers.Player, "Player", Kilobytes(256));
- ClaimBuffer(&MemoryArena, &CollationBuffers.Script, "Script", Kilobytes(8));
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.IncludesPlayer, "IncludesPlayer", Kilobytes(1)) == RC_ARENA_FULL) { goto RIP; };
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.Menus, "Menus", Kilobytes(24)) == RC_ARENA_FULL) { goto RIP; };
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.Player, "Player", Kilobytes(256)) == RC_ARENA_FULL) { goto RIP; };
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.Script, "Script", Kilobytes(8)) == RC_ARENA_FULL) { goto RIP; };
- ClaimBuffer(&MemoryArena, &CollationBuffers.IncludesIndex, "IncludesIndex", Kilobytes(1));
- ClaimBuffer(&MemoryArena, &CollationBuffers.Index, "Index", Kilobytes(8));
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.IncludesIndex, "IncludesIndex", Kilobytes(1)) == RC_ARENA_FULL) { goto RIP; };
+ if(ClaimBuffer(&MemoryArena, &CollationBuffers.Index, "Index", Kilobytes(8)) == RC_ARENA_FULL) { goto RIP; };
*CollationBuffers.Title = '\0';
- buffer Template;
- Template.ID = "Template";
+ template *PlayerTemplateMetadata;
+ template *IndexTemplateMetadata;
if(Config.Mode == MODE_INTEGRATE)
{
- ValidateTemplate(&Template, Config);
+ if(ClaimTemplate(&MemoryArena, &PlayerTemplateMetadata, Config.TemplatePlayerLocation) == RC_ARENA_FULL) { goto RIP; };
+ switch(ValidateTemplate(&Errors, PlayerTemplateMetadata, Config, PAGE_PLAYER))
+ {
+ case RC_INVALID_TEMPLATE: // Invalid template
+ case RC_ERROR_FILE: // Could not load template
+ case RC_ERROR_MEMORY: // Could not allocate memory for template
+ goto RIP;
+ case RC_SUCCESS:
+ break;
+ }
+
+ if(Config.Edition == EDITION_PROJECT)
+ {
+ if(ClaimTemplate(&MemoryArena, &IndexTemplateMetadata, Config.TemplateIndexLocation) == RC_ARENA_FULL) { goto RIP; };
+ switch(ValidateTemplate(&Errors, IndexTemplateMetadata, Config, PAGE_INDEX))
+ {
+ case RC_INVALID_TEMPLATE: // Invalid template
+ case RC_ERROR_MEMORY: // Could not allocate memory for template
+ case RC_ERROR_FILE: // Could not load template
+ goto RIP;
+ case RC_SUCCESS:
+ break;
+ }
+ }
}
// NOTE(matt)
@@ -3229,82 +3546,73 @@ main(int ArgC, char **Args)
if(Config.Edition == EDITION_PROJECT)
{
- DIR *ProjectDirHandle;
- if(!(ProjectDirHandle = opendir(Config.ProjectDir)))
+ switch(RefreshProject(&MemoryArena, &CollationBuffers, IndexTemplateMetadata, PlayerTemplateMetadata, Config))
{
- perror(Config.ProjectDir);
- // TODO(matt):
- // Cleanup
- }
-
- struct dirent *ProjectFiles;
- int FileIndex = 0;
- while((ProjectFiles = readdir(ProjectDirHandle)))
- {
- // TODO(matt):
- char *Ptr = ProjectFiles->d_name;
- Ptr += (StringLength(ProjectFiles->d_name) - StringLength(".hmml"));
- if(!(StringsDiffer(Ptr, ".hmml")))
- {
- *Ptr = '\0';
- char BaseFilename[255];
- CopyString(BaseFilename, ProjectFiles->d_name);
- *Ptr = '.';
-
- char OutputDir[255];
- CopyString(OutputDir, "%s/%s", Config.BaseDir, BaseFilename);
- // TODO(matt): Check
- char OutputPath[255];
- CopyString(OutputPath, "%s/index.html", OutputDir);
- DIR *OutputDirectoryHandle;
- if(!(OutputDirectoryHandle = opendir(OutputDir)))
- {
- MakeDir(OutputDir);
- }
- closedir(OutputDirectoryHandle);
-
- HMMLToBuffers(&MemoryArena, &CollationBuffers, Config, ProjectFiles->d_name);
- BuildIndex(&MemoryArena, &CollationBuffers, Config, BaseFilename, CollationBuffers.Title);
- ++FileIndex;
- BuffersToHTML(&MemoryArena, CollationBuffers, Template, Config, OutputPath);
- }
- }
- closedir(ProjectDirHandle);
-
- if(Config.Edition == EDITION_SINGLE && optind == ArgC)
- {
- fprintf(stderr, "%s: requires at least one input .hmml file\n", Args[0]);
- PrintUsage(Args[0], DefaultConfig);
- return 1;
+ case RC_ERROR_DIRECTORY:
+ case RC_ERROR_FATAL:
+ // HERE
+ goto RIP;
+ case RC_SUCCESS:
+ break;
}
}
else
{
+ if(optind == ArgC)
+ {
+ fprintf(stderr, "%s: requires at least one input .hmml file\n", Args[0]);
+ PrintUsage(Args[0], DefaultConfig);
+ goto RIP;
+ }
+
+NextFile:
for(int FileIndex = optind; FileIndex < ArgC; ++FileIndex)
{
- HMMLToBuffers(&MemoryArena, &CollationBuffers, Config, Args[FileIndex]);
- BuffersToHTML(&MemoryArena, CollationBuffers, Template, Config, Args[FileIndex]);
+ switch(HMMLToBuffers(&MemoryArena, &CollationBuffers, Config, Args[FileIndex]))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_ERROR_FILE:
+ case RC_ERROR_FATAL:
+ goto RIP;
+ case RC_ERROR_HMML:
+ case RC_ERROR_MAX_REFS:
+ case RC_ERROR_QUOTE:
+ case RC_INVALID_REFERENCE:
+ goto NextFile;
+ case RC_SUCCESS:
+ break;
+ };
+ switch(BuffersToHTML(&MemoryArena, CollationBuffers, PlayerTemplateMetadata, Config, 0, PAGE_PLAYER))
+ {
+ // TODO(matt): Actually sort out the fatality of these cases, once we are always-on
+ case RC_INVALID_TEMPLATE:
+ LogError(Config, LOG_ERROR, "Invalid player template: %s", PlayerTemplateMetadata->Filename);
+ case RC_ERROR_MEMORY:
+ case RC_ERROR_FILE:
+ case RC_ARENA_FULL:
+ goto RIP;
+ case RC_SUCCESS:
+ break;
+ };
}
}
if(Config.Mode == MODE_INTEGRATE)
{
- FreeBuffer(&Template);
+ DeclaimTemplate(&MemoryArena, &PlayerTemplateMetadata);
+ if(Config.Edition == EDITION_PROJECT)
+ {
+ DeclaimTemplate(&MemoryArena, &IndexTemplateMetadata);
+ }
}
- // TODO(matt): Handle return codes
-#endif
-
-
- // TODO(matt)
-#if 1
-#endif
-
DeclaimBuffer(&MemoryArena, &CollationBuffers.Index);
DeclaimBuffer(&MemoryArena, &CollationBuffers.IncludesIndex);
DeclaimBuffer(&MemoryArena, &CollationBuffers.Script);
DeclaimBuffer(&MemoryArena, &CollationBuffers.Player);
DeclaimBuffer(&MemoryArena, &CollationBuffers.Menus);
DeclaimBuffer(&MemoryArena, &CollationBuffers.IncludesPlayer);
+ DeclaimBuffer(&MemoryArena, &Errors);
+RIP:
free(MemoryArena.Location);
}