hmml_to_html.c: Always On

This commit is contained in:
Matt Mascarenhas 2017-09-15 02:11:39 +01:00
parent d82e665310
commit b133f15a11
1 changed files with 68 additions and 10 deletions

View File

@ -25,7 +25,8 @@ typedef unsigned int bool;
#include <dirent.h> #include <dirent.h>
#include <string.h> // NOTE(matt): strerror #include <string.h> // NOTE(matt): strerror
#include <errno.h> //NOTE(matt): errno #include <errno.h> //NOTE(matt): errno
#include <sys/inotify.h> // NOTE(matt): inotify
#include <unistd.h> // NOTE(matt): sleep()
#define Kilobytes(Bytes) Bytes << 10 #define Kilobytes(Bytes) Bytes << 10
#define Megabytes(Bytes) Bytes << 20 #define Megabytes(Bytes) Bytes << 20
@ -450,6 +451,7 @@ MakeDir(char *Path)
void void
LogUsage(buffer Buffer, char *CacheDir) LogUsage(buffer Buffer, char *CacheDir)
{ {
#if DEBUG
char LogPath[255]; char LogPath[255];
CopyString(LogPath, "%s/%s", CacheDir, "buffers.log"); CopyString(LogPath, "%s/%s", CacheDir, "buffers.log");
FILE *LogFile; FILE *LogFile;
@ -468,6 +470,7 @@ LogUsage(buffer Buffer, char *CacheDir)
Buffer.Ptr - Buffer.Location, Buffer.Ptr - Buffer.Location,
Buffer.Size); Buffer.Size);
fclose(LogFile); fclose(LogFile);
#endif
} }
__attribute__ ((format (printf, 3, 4))) __attribute__ ((format (printf, 3, 4)))
@ -3144,6 +3147,7 @@ RefreshIndex(arena *MemoryArena, buffers *CollationBuffers, config Config, char
{ {
LogError(Config, LOG_ERROR, "RefreshIndex(): %s", strerror(errno)); LogError(Config, LOG_ERROR, "RefreshIndex(): %s", strerror(errno));
free(Index.Location); free(Index.Location);
fclose(IndexFile);
return RC_ERROR_MEMORY; return RC_ERROR_MEMORY;
} }
Scratch.Ptr = Scratch.Location; Scratch.Ptr = Scratch.Location;
@ -3154,14 +3158,17 @@ RefreshIndex(arena *MemoryArena, buffers *CollationBuffers, config Config, char
*Scratch.Ptr = '\0'; *Scratch.Ptr = '\0';
Index.Ptr = Index.Location + Head; Index.Ptr = Index.Location + Head;
CopyStringToBuffer(&Index, "%s,%s\n", BaseFilename, CollationBuffers->Title); CopyStringToBuffer(&Index, "%s,%s\n"
"%s",
BaseFilename, CollationBuffers->Title,
Scratch.Location);
CopyStringToBuffer(&Index, Scratch.Location);
free(Scratch.Location); free(Scratch.Location);
Index.Size = Index.Ptr - Index.Location;
fclose(IndexFile); fclose(IndexFile);
IndexFile = fopen(IndexPath, "w"); IndexFile = fopen(IndexPath, "w");
fwrite(Index.Location, Index.Ptr - Index.Location, 1, IndexFile); fwrite(Index.Location, Index.Size, 1, IndexFile);
Inserted = TRUE; Inserted = TRUE;
} }
@ -3176,19 +3183,22 @@ RefreshIndex(arena *MemoryArena, buffers *CollationBuffers, config Config, char
++EntryCount; ++EntryCount;
} }
if(Found == FALSE) if(!Found)
{ {
++EntryCount; ++EntryCount;
// TODO(matt): Write the EntryCount into the index // TODO(matt): Write the EntryCount into the index
if(Inserted == FALSE) if(!Inserted)
{ {
CopyStringToBuffer(&Index, "%s,%s\n", BaseFilename, CollationBuffers->Title);
fprintf(IndexFile, "%s,%s\n", BaseFilename, CollationBuffers->Title); fprintf(IndexFile, "%s,%s\n", BaseFilename, CollationBuffers->Title);
} }
RewindBuffer(&CollationBuffers->Index); RewindBuffer(&CollationBuffers->Index);
Index.Size = Index.Ptr - Index.Location;
RewindBuffer(&Index);
CopyStringToBuffer(&CollationBuffers->Index, "<dl>\n"); CopyStringToBuffer(&CollationBuffers->Index, "<dl>\n");
Index.Ptr = Index.Location; while(Index.Ptr - Index.Location < Index.Size)
while(Index.Ptr - Index.Location < IndexFileSize)
{ {
char IndexedFile[32]; char IndexedFile[32];
char *Ptr = IndexedFile; char *Ptr = IndexedFile;
@ -3198,6 +3208,13 @@ RefreshIndex(arena *MemoryArena, buffers *CollationBuffers, config Config, char
Ptr = Title; Ptr = Title;
Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, '\n') + 1; Index.Ptr += CopyStringNoFormatT(Ptr, Index.Ptr, '\n') + 1;
// TODO(matt): Fully figure out why the Table of Contents doesn't always get all the stuff from the index
// Steps to reproduce:
// 1. mv riscy04{4..6}.hmml out of the way
// 2. Call the program
// 3. mv riscy046.hmml into the project directory
// 4. See that riscy046 is in the index file, has its own player page, but is not mentioned in the Table of Contents
CopyStringToBuffer(&CollationBuffers->Index, CopyStringToBuffer(&CollationBuffers->Index,
" <dt>\n" " <dt>\n"
" <a href=\"%s\">%s</a>\n" " <a href=\"%s\">%s</a>\n"
@ -3330,6 +3347,38 @@ NextFile:
return RC_SUCCESS; return RC_SUCCESS;
} }
int
MonitorDirectory(arena *MemoryArena, buffers *CollationBuffers, template *IndexTemplateMetadata, template *PlayerTemplateMetadata, config Config, int inotifyInstance, int WatchDescriptor)
{
buffer Events;
if(ClaimBuffer(MemoryArena, &Events, "inotify Events", Kilobytes(4)) == RC_ARENA_FULL) { return RC_ARENA_FULL; };
struct inotify_event *Event;
int BytesRead;
while((BytesRead = read(inotifyInstance, Events.Location, Events.Size)) != -1 && errno == EAGAIN && BytesRead > 0)
{
for(Events.Ptr = Events.Location;
Events.Ptr < Events.Location + BytesRead;
Events.Ptr += sizeof(struct inotify_event) + Event->len)
{
Event = (struct inotify_event *)Events.Ptr;
switch(RefreshProject(MemoryArena, CollationBuffers, IndexTemplateMetadata, PlayerTemplateMetadata, Config))
{
case RC_ERROR_DIRECTORY:
case RC_ERROR_FATAL:
DeclaimBuffer(MemoryArena, &Events);
return RC_ERROR_FATAL;
case RC_SUCCESS:
break;
}
}
}
DeclaimBuffer(MemoryArena, &Events);
return RC_SUCCESS;
}
int int
main(int ArgC, char **Args) main(int ArgC, char **Args)
{ {
@ -3550,11 +3599,19 @@ main(int ArgC, char **Args)
{ {
case RC_ERROR_DIRECTORY: case RC_ERROR_DIRECTORY:
case RC_ERROR_FATAL: case RC_ERROR_FATAL:
// HERE
goto RIP; goto RIP;
case RC_SUCCESS: case RC_SUCCESS:
break; break;
} }
int inotifyInstance = inotify_init1(IN_NONBLOCK);
int WatchDescriptor = inotify_add_watch(inotifyInstance, Config.ProjectDir, IN_CLOSE_WRITE | IN_MOVED_TO);
while(MonitorDirectory(&MemoryArena, &CollationBuffers, IndexTemplateMetadata, PlayerTemplateMetadata, Config, inotifyInstance, WatchDescriptor) == RC_SUCCESS)
{
// TODO(matt): Make this update frequency configurable
sleep(1);
}
} }
else else
{ {
@ -3578,7 +3635,8 @@ NextFile:
case RC_ERROR_MAX_REFS: case RC_ERROR_MAX_REFS:
case RC_ERROR_QUOTE: case RC_ERROR_QUOTE:
case RC_INVALID_REFERENCE: case RC_INVALID_REFERENCE:
goto NextFile; if(FileIndex < (ArgC - 1)) { goto NextFile; }
else { goto RIP; }
case RC_SUCCESS: case RC_SUCCESS:
break; break;
}; };