Bit of a mess but it correctly parses and doesnt leak

main
Alan Francis 1 year ago
parent 7c4677feb4
commit 0c35672ca0
  1. 378
      configmodel.c
  2. 23
      configmodel.h
  3. 2
      containers/linearray.h
  4. 18
      containers/linemap.c
  5. 13
      containers/linemap.h
  6. 1
      containers/sectionarray.h
  7. 2
      containers/sectionmap.h
  8. 13
      containers/stringarray.c
  9. 5
      containers/stringarray.h
  10. 74
      cregex/pattern.c
  11. 10
      cregex/pattern.h
  12. 3
      main.c
  13. 192
      sectionstore.c
  14. 11
      sectionstore.h
  15. 11
      smakefile
  16. 11
      types.h

@ -12,38 +12,10 @@
#define ZERO ((BPTR)0)
cregex_program_t* InitialisePattern(CONST_STRPTR pattern);
Array RunPattern(CONST_STRPTR text, cregex_program_t* patternProgram);
SECTIONPTR LineGetSection(LINEPTR abstractLine);
VARIABLEPTR LineGetVariable(LINEPTR abstractLine);
VOID LineDump(LINEPTR abstractLine);
SECTIONPTR SectionCreateWithName(CONST_STRPTR primary);
SECTIONPTR SectionCreateWithNameAndSubname(CONST_STRPTR primary, CONST_STRPTR secondary);
VOID SectionFree(SECTIONPTR abstractSection);
VARIABLEPTR VariableCreate(CONST_STRPTR key, CONST_STRPTR rawValue);
VOID VariableFree(VARIABLEPTR abstractVariable);
#define WHITESPACE "[ \\t\\n\\r\\f\\v]"
#define RX_BLANK_LINE "^[ \t\n\r\f\v]*($|#|;)"
#define RX_SECTION_LINE "^[ \t\n\r\f\v]*\\[([a-z0-9]+)([ \t\n\r\f\v]*\"(.+)\")*\\][ \t\n\r\f\v]*($|#|;)"
#define RX_VARIABLE_LINE "^[ \t\n\r\f\v]*([a-z][a-z0-9]+)[ \t\n\r\f\v]*=[ \t\n\r\f\v]*(.+)[ \t\n\r\f\v]*($|#|;)"
#define RX_INTEGER "^-?[1-9][0-9]*$"
STATIC cregex_program_t* sectionPatternProgram = NULL;
STATIC cregex_program_t* variablePatternProgram = NULL;
STATIC cregex_program_t* blankPatternProgram = NULL;
STATIC cregex_program_t* integerPatternProgram = NULL;
// - STRUCTS -----------------------------------------------------------------------------
struct ConfigFile
{
CONST_STRPTR filename;
LineArray lines;
SECTIONSTOREPTR sectionStore;
};
@ -80,16 +52,15 @@ struct Line
struct Section* section;
};
// ---------------------------------------------------------------------------------------
// - CONFIG FILE -------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
VOID ConfigFileFree(CONFIGFILEPTR abstractConfigFile)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
if( configFile->lines != NULL )
{
LineArrayFree(configFile->lines, TRUE); //also frees lines
}
if( configFile->sectionStore != NULL )
{
SectionStoreFree(configFile->sectionStore);
@ -98,6 +69,8 @@ VOID ConfigFileFree(CONFIGFILEPTR abstractConfigFile)
}
}
STATIC LINEPTR configFileReadLine(BPTR file);
CONFIGFILEPTR ConfigFileRead(CONST_STRPTR filename)
{
struct ConfigFile* result = AllocVec(sizeof(struct ConfigFile), MEMF_CLEAR);
@ -105,162 +78,193 @@ CONFIGFILEPTR ConfigFileRead(CONST_STRPTR filename)
if( configFile != ZERO )
{
LINEPTR line = NULL;
SECTIONPTR currentSection = NULL;//SectionCreateWithName(""); // initial empty section
result->sectionStore = SectionStoreNew();
result->lines = LineArrayNew();
InitialisePatterns();
while( (line = LineReadIncludingContinuation(configFile, result->sectionStore, currentSection)) != NULL )
while( (line = configFileReadLine(configFile)) != NULL )
{
// add it to the flat list of lines
LineArrayAppend(result->lines, line);
LineDump(line);
if( LineGetSection(line) != NULL )
{
currentSection = LineGetSection(line);
}
SectionStoreAddLine(result->sectionStore, line);
//LineDump(line);
}
ReleasePatterns();
Close(configFile);
}
return result;
}
VOID ConfigFileSave(CONFIGFILEPTR config)
VOID SectionDump(SECTIONPTR abstractSection)
{
struct Section* section = (struct Section*)abstractSection;
if( section != NULL && section->lines != NULL )
{
ArrayForEach(LINEPTR, aLine, section->lines, LineDump(aLine););
}
}
LINEPTR LineCreate(CONST_STRPTR buffer, ULONG size, SECTIONSTOREPTR sectionStore)
VOID ConfigFileDump(CONFIGFILEPTR abstractConfigFile)
{
ULONG index = 0;
ULONG count = 0;
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
count = SectionStoreSectionCount(configFile->sectionStore);
for( index = 0; index < count; index++ )
{
SECTIONPTR section = SectionStoreSectionAt(configFile->sectionStore, index);
SectionDump(section);
}
}
}
STATIC LINEPTR configFileReadLine(BPTR file)
{
UBYTE* buffer = AllocVec(512, MEMF_CLEAR);
ULONG bufLength = 512;
ULONG bytesReadTotal = 0;
UBYTE* read = NULL;
struct Line* result = NULL;
StringArray matches = NULL;
// read the whole line including continuation
do
{
read = FGets(file, &(buffer[bytesReadTotal]), bufLength-bytesReadTotal);
bytesReadTotal = strlen(buffer);
}
while( read != NULL && bytesReadTotal >= 2 && bytesReadTotal < bufLength && buffer[bytesReadTotal-1] == '\n' && buffer[bytesReadTotal-2] == '\\' );
// make a line
if( bytesReadTotal > 0 )
{
result = LineNew(buffer, bytesReadTotal);
}
FreeVec(buffer);
return result;
}
// ---------------------------------------------------------------------------------------
// - LINE --------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
LINEPTR LineNew(CONST_STRPTR buffer, ULONG size)
{
struct Line* result = NULL;
if( size > 0 )
{
result = AllocVec(sizeof(struct Line), MEMF_CLEAR);
result->rawText = AllocVec(size, MEMF_CLEAR);
CopyMem(buffer, result->rawText, size-1); // drop the \\n
if( matches = RunPattern(result->rawText, sectionPatternProgram) )
{
SECTIONPTR section = NULL;
if( SizeOfArray(matches) == 3 )
{
section = SectionCreateWithName(StringArrayValues(matches)[1]);
}
else if( SizeOfArray(matches) == 5 )
{
section = SectionCreateWithNameAndSubname(StringArrayValues(matches)[1], StringArrayValues(matches)[3]);
}
if( section != NULL )
{
SectionStoreAddSection(sectionStore, section);
result->section = section;
}
StringArrayFree(matches);
}
else
{
if( matches = RunPattern(result->rawText, variablePatternProgram) )
{
result->variable = VariableCreate(StringArrayValues(matches)[1], StringArrayValues(matches)[2]);
StringArrayFree(matches);
}
else
{
if( matches = RunPattern(result->rawText, blankPatternProgram) )
{
StringArrayFree(matches);
}
else
{
Printf("\nDIDNT MATCH ANYTHING %s\n", result->rawText);
}
}
}
}
return result;
}
STATIC VOID lineDumpRecreate(LINEPTR abstractLine);
VOID LineDump(LINEPTR abstractLine)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
Printf("> %s\n", line->rawText);
if( line->rawText != NULL )
{
Printf("%s\n", line->rawText);
}
else
{
lineDumpRecreate(line);
}
}
}
STATIC VOID lineDumpRecreate(LINEPTR abstractLine)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
if( line->variable == NULL && line->section == NULL )
{
Printf("(blank)\n");
// blank
Printf("# blank line\n");
}
else if( line->variable == NULL && line->section != NULL )
{
// section
struct Section* section = (struct Section*)LineGetSection(abstractLine);
CONST_STRPTR canonical = NULL;
Printf("(new section %s", section->primary);
if( section->secondary )
if( section != NULL && section->primary != NULL )
{
Printf("[%s]", section->secondary);
if( strlen(section->primary) > 0 )
{
Printf("[%s", section->primary);
if( section->secondary != NULL )
{
Printf(" \"%s\"", section->secondary);
}
Printf("]\n");
}
}
Printf(")\n");
canonical = SectionCanonicalName(section);
Printf("...((%s))...\n", canonical);
FreeVec((STRPTR)canonical);
}
else
{
struct Section* section = (struct Section*)LineGetSection(abstractLine);
struct Variable* var = (struct Variable*)LineGetVariable(abstractLine);
Printf("(variable in section %s", section->primary);
if( section->secondary )
{
Printf("[%s]\n", section->secondary);
}
Printf(") %s = %s\n", var->key, var->value.stringValue);
Printf("%s = %s\n", var->key, var->value.stringValue);
}
}
}
LINEPTR LineReadIncludingContinuation(BPTR file, SECTIONSTOREPTR sectionStore, SECTIONPTR currentSection)
VOID LineSetSection(LINEPTR abstractLine, SECTIONPTR abstractSection)
{
UBYTE* buffer = AllocVec(512, MEMF_CLEAR);
ULONG bufLength = 512;
ULONG bytesReadTotal = 0;
UBYTE* read = NULL;
struct Line* result = NULL;
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
// we dont own the section
line->section = abstractSection;
}
}
// read the whole line including continuation
do
SECTIONPTR LineGetSection(LINEPTR abstractLine)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
read = FGets(file, &(buffer[bytesReadTotal]), bufLength-bytesReadTotal);
bytesReadTotal = strlen(buffer);
}
while( read != NULL && bytesReadTotal >= 2 && bytesReadTotal < bufLength && buffer[bytesReadTotal-1] == '\n' && buffer[bytesReadTotal-2] == '\\' );
// make a line
if( bytesReadTotal > 0 )
return line->section;
}
return NULL;
}
// first time through we need to preserve rawText
VOID LineSetInitialVariable(LINEPTR abstractLine, VARIABLEPTR abstractVariable)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
result = LineCreate(buffer, bytesReadTotal, sectionStore);
if( result->variable != NULL && result->section == NULL )
// we take ownership of the variable
if( line->variable != NULL )
{
result->section = currentSection;
VariableFree(line->variable);
}
line->variable = abstractVariable;
}
FreeVec(buffer);
return result;
}
SECTIONPTR LineGetSection(LINEPTR abstractLine)
// any further change to the variable means we wipe the raw text
VOID LineSetVariable(LINEPTR abstractLine, VARIABLEPTR abstractVariable)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
return line->section;
if( line->rawText != NULL )
{
// if we change the variable we remove any original text
FreeVec(line->rawText);
line->rawText = NULL;
}
// we take ownership of the variable
if( line->variable != NULL )
{
VariableFree(line->variable);
}
line->variable = abstractVariable;
}
return NULL;
}
VARIABLEPTR LineGetVariable(LINEPTR abstractLine)
@ -304,6 +308,9 @@ CONST_STRPTR LineGetRawText(LINEPTR abstractLine)
}
}
// ---------------------------------------------------------------------------------------
// - SECTION -----------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
SECTIONPTR SectionCreateWithName(CONST_STRPTR primary)
{
@ -334,6 +341,22 @@ SECTIONPTR SectionCreateWithNameAndSubname(CONST_STRPTR primary, CONST_STRPTR se
return result;
}
VOID SectionAddSectionLine(SECTIONPTR abstractSection, LINEPTR abstractLine)
{
// sets self onto line and then adds line to the collection
LineSetSection(abstractLine, abstractSection);
SectionAddLine(abstractSection, abstractLine);
}
VOID SectionAddLine(SECTIONPTR abstractSection, LINEPTR abstractLine)
{
struct Section* section = (struct Section*)abstractSection;
if( section != NULL )
{
LineArrayAppend(section->lines, abstractLine);
}
}
VOID SectionFree(SECTIONPTR abstractSection)
{
struct Section* section = (struct Section*)abstractSection;
@ -349,7 +372,7 @@ VOID SectionFree(SECTIONPTR abstractSection)
}
if( section->lines != NULL )
{
LineArrayFree(section->lines, FALSE); // dont free the lines they are only weak
LineArrayFree(section->lines, TRUE); // free the lines when we free the section
}
FreeVec(section);
}
@ -379,6 +402,9 @@ CONST_STRPTR SectionCanonicalName(SECTIONPTR abstractSection)
return result;
}
// ---------------------------------------------------------------------------------------
// - VARIABLE ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
VARIABLEPTR VariableCreate(CONST_STRPTR key, CONST_STRPTR rawValue)
{
@ -418,93 +444,3 @@ VOID VariableFree(VARIABLEPTR abstractVariable)
}
}
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
VOID InitialisePatterns(VOID)
{
sectionPatternProgram = InitialisePattern(RX_SECTION_LINE);
variablePatternProgram = InitialisePattern(RX_VARIABLE_LINE);
blankPatternProgram = InitialisePattern(RX_BLANK_LINE);
integerPatternProgram = InitialisePattern(RX_INTEGER);
}
VOID ReleasePatterns(VOID)
{
if( sectionPatternProgram != NULL ) cregex_compile_free( sectionPatternProgram );
if( variablePatternProgram != NULL ) cregex_compile_free( variablePatternProgram );
if( blankPatternProgram != NULL ) cregex_compile_free( blankPatternProgram );
if( integerPatternProgram != NULL ) cregex_compile_free( integerPatternProgram );
}
cregex_program_t* InitialisePattern(CONST_STRPTR pattern)
{
cregex_program_t* result = NULL;
cregex_node_t* patternNode = cregex_parse(pattern);
if( patternNode )
{
result = cregex_compile_node( patternNode );
if( result != NULL )
{
//Printf("successfully compiled %s\n", pattern);
}
else
{
Printf("failed to compile %s\n", pattern);
}
cregex_parse_free( patternNode );
}
else
{
Printf("could not parse %s\n", pattern);
}
return result;
}
Array RunPattern(CONST_STRPTR text, cregex_program_t* patternProgram)
{
Array result = NULL;
char* localMatches[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (cregex_program_run(patternProgram, text, localMatches, 20) > 0) {
int j = 0;
int nmatches = 0;
// count the matches
for (j = 0; j < 20; ++j)
if (localMatches[j])
nmatches = j;
if( nmatches > 0 )
{
result = StringArrayNew();
// loop the matches
for (j = 0; j <= nmatches; j += 2) {
if (localMatches[j] && localMatches[j + 1]) {
int len = (int)(localMatches[j + 1] - localMatches[j]);
STRPTR buffer = AllocVec(len+1, MEMF_CLEAR); // freed in the array
sprintf(buffer, "%.*s", len, localMatches[j]);
if( buffer[len-1] == '\n' )
{
buffer[len-1] = '\0';
}
StringArrayAppend(result, buffer);
} else {
//Printf("(NULL,NULL)\n");
}
}
}
// end
} else {
//Printf("\"%s\": no match\n", text);
}
return result;
}

@ -4,23 +4,32 @@
#include <dos/dos.h>
CONFIGFILEPTR ConfigFileRead(CONST_STRPTR filename);
VOID ConfigFileFree(CONFIGFILEPTR abstractConfigFile);
VOID ConfigFileFree(CONFIGFILEPTR configFile);
VOID ConfigFileDump(CONFIGFILEPTR configFile);
VOID ConfigFileSave(CONFIGFILEPTR config);
VOID InitialisePatterns(VOID);
VOID ReleasePatterns(VOID);
LINEPTR LineReadIncludingContinuation(BPTR file, SECTIONPTR currentSection, SECTIONSTOREPTR sectionStore);
LINEPTR LineNew(CONST_STRPTR buffer, ULONG size);
VOID LineFree(LINEPTR abstractLine);
CONST_STRPTR LineGetRawText(LINEPTR line);
VOID LineSetSection(LINEPTR line, SECTIONPTR section);
SECTIONPTR LineGetSection(LINEPTR line);
VARIABLEPTR LineGetVariable(LINEPTR line);
VOID LineSetInitialVariable(LINEPTR line, VARIABLEPTR variable);
VOID LineSetVariable(LINEPTR line, VARIABLEPTR variable);
VOID LineDump(LINEPTR abstractLine);
SECTIONPTR SectionCreateWithName(CONST_STRPTR primary);
SECTIONPTR SectionCreateWithNameAndSubname(CONST_STRPTR primary, CONST_STRPTR secondary);
VOID SectionFree(SECTIONPTR section);
VOID SectionAddSectionLine(SECTIONPTR section, LINEPTR line);
VOID SectionAddLine(SECTIONPTR section, LINEPTR line);
CONST_STRPTR SectionCanonicalName(SECTIONPTR section);
VOID SectionDump(SECTIONPTR section);
VARIABLEPTR VariableCreate(CONST_STRPTR key, CONST_STRPTR rawValue);
VOID VariableFree(VARIABLEPTR abstractVariable);
VOID VariableFree(VARIABLEPTR variable);
#endif

@ -6,8 +6,6 @@
#include <dos/dos.h>
#include "configmodel.h"
#define LineArray Array
LineArray LineArrayNew(VOID);
VOID LineArrayAppend(LineArray array, LINEPTR value);
VOID LineArrayFree(LineArray array, BOOL freeLines);

@ -1,18 +0,0 @@
#include "linemap.h"
#include "linearray.h"
LineMap LineMapNew()
{
LineMap result = NewMap(CNTKIT_KEY_STRING,
CNTKIT_CAPACITY, 8,
CNTKIT_VALUESIZE, 4,
TAG_DONE);
return result;
}
VOID LineMapFree(LineMap map)
{
// doesnt seem to delete contents
DeleteMap(map);
}

@ -1,13 +0,0 @@
#ifndef __LINEMAP_H
#define __LINEMAP_H
#include <exec/types.h>
#include <proto/containerkit.h>
#include "configmodel.h"
#define LineMap Map
LineMap LineMapNew(VOID);
VOID LineMapFree(LineMap map);
#endif

@ -4,7 +4,6 @@
#include <exec/types.h>
#include <proto/containerkit.h>
#include "configmodel.h"
#define SectionArray Array
SectionArray SectionArrayNew(VOID);
VOID SectionArrayAppend(SectionArray array, SECTIONPTR value);

@ -5,8 +5,6 @@
#include <proto/containerkit.h>
#include "configmodel.h"
#define SectionMap Map // a map of string (canonical name) to Section
SectionMap SectionMapNew(VOID);
VOID SectionMapSet(SectionMap map, CONST_STRPTR canonicalName, SECTIONPTR section);
SECTIONPTR SectionMapGet(SectionMap map, CONST_STRPTR canonicalName);

@ -1,27 +1,28 @@
#include "stringarray.h"
#include "configmodel.h"
#include <proto/containerkit.h>
#include <proto/exec.h>
#include <string.h>
Array StringArrayNew(VOID)
StringArray StringArrayNew(VOID)
{
#define SIZE_STRPTR 2
return NewArray(SIZE_STRPTR);
}
VOID StringArrayAppend(Array array, CONST_STRPTR value)
VOID StringArrayAppend(StringArray array, CONST_STRPTR value)
{
AppendToArray(CONST_STRPTR, array, value);
}
VOID StringArrayAppendAndRetain(Array array, CONST_STRPTR value)
VOID StringArrayAppendAndRetain(StringArray array, CONST_STRPTR value)
{
STRPTR localCopy = AllocVec(strlen(value)+1, MEMF_CLEAR);
CopyMem(value, localCopy, strlen(value));
StringArrayAppend(array, localCopy);
}
VOID StringArrayFree(Array array)
VOID StringArrayFree(StringArray array)
{
if( array != NULL )
{
@ -30,7 +31,7 @@ VOID StringArrayFree(Array array)
}
}
CONST_STRPTR* StringArrayValues(Array array)
CONST_STRPTR* StringArrayValues(StringArray array)
{
return ArrayValues(CONST_STRPTR, array);
}

@ -1,10 +1,7 @@
#ifndef __STRINGARRAY_H
#define __STRINGARRAY_H
#include <exec/types.h>
#include <proto/containerkit.h>
#define StringArray Array
#include "types.h"
StringArray StringArrayNew(VOID);
VOID StringArrayAppend(StringArray array, CONST_STRPTR value);

@ -0,0 +1,74 @@
#include "pattern.h"
#include "cregex.h"
#include "containers/stringarray.h"
#include <proto/exec.h>
#include <stdio.h>
PATTERNPTR PatternNew(CONST_STRPTR pattern)
{
cregex_program_t* result = NULL;
cregex_node_t* patternNode = cregex_parse(pattern);
if( patternNode )
{
result = cregex_compile_node( patternNode );
if( result != NULL )
{
//Printf("successfully compiled %s\n", pattern);
}
else
{
// Printf("failed to compile %s\n", pattern);
}
cregex_parse_free( patternNode );
}
else
{
// Printf("could not parse %s\n", pattern);
}
return result;
}
VOID PatternFree(cregex_program_t* pattern)
{
cregex_compile_free( pattern );
}
StringArray PatternRun(CONST_STRPTR text, cregex_program_t* patternProgram)
{
StringArray result = NULL;
char* localMatches[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (cregex_program_run(patternProgram, text, localMatches, 20) > 0) {
int j = 0;
int nmatches = 0;
// count the matches
for (j = 0; j < 20; ++j)
if (localMatches[j])
nmatches = j;
if( nmatches > 0 )
{
result = StringArrayNew();
// loop the matches
for (j = 0; j <= nmatches; j += 2) {
if (localMatches[j] && localMatches[j + 1]) {
int len = (int)(localMatches[j + 1] - localMatches[j]);
STRPTR buffer = AllocVec(len+1, MEMF_CLEAR); // freed in the array
sprintf(buffer, "%.*s", len, localMatches[j]);
if( buffer[len-1] == '\n' )
{
buffer[len-1] = '\0';
}
StringArrayAppend(result, buffer);
} else {
//Printf("(NULL,NULL)\n");
}
}
}
// end
} else {
//Printf("\"%s\": no match\n", text);
}
return result;
}

@ -0,0 +1,10 @@
#ifndef __CONFIGREGEX_H
#define __CONFIGREGEX_H
#include "types.h"
PATTERNPTR PatternNew(CONST_STRPTR pattern);
VOID PatternFree(PATTERNPTR pattern);
StringArray PatternRun(CONST_STRPTR text, PATTERNPTR patternProgram);
#endif

@ -24,6 +24,9 @@ WORD DoTheWork(STRPTR filename)
CONFIGFILEPTR config = ConfigFileRead(filename);
if( config != NULL )
{
Printf("XXXXXXX\n");
ConfigFileDump(config);
Printf("XXXXXXX\n");
ConfigFileFree(config);
}
else

@ -1,13 +1,35 @@
#include "sectionstore.h"
#include "containers/sectionmap.h"
#include "containers/sectionarray.h"
#include "containers/stringarray.h"
#include "cregex/pattern.h"
#include <proto/exec.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define RX_SECTION_LINE "^[ \t\n\r\f\v]*\\[([a-z0-9]+)([ \t\n\r\f\v]*\"(.+)\")*\\][ \t\n\r\f\v]*($|#|;)"
#define RX_VARIABLE_LINE "^[ \t\n\r\f\v]*([a-z][a-z0-9]+)[ \t\n\r\f\v]*=[ \t\n\r\f\v]*(.+)[ \t\n\r\f\v]*($|#|;)"
#define RX_INTEGER "^-?[1-9][0-9]*$"
#define RX_BLANK_LINE "^[ \t\n\r\f\v]*($|#|;)"
STATIC SECTIONPTR parseSection(LINEPTR line, PATTERNPTR sectionPatternProgram);
STATIC VARIABLEPTR parseVariable(LINEPTR line, PATTERNPTR variablePatternProgram);
STATIC BOOL parseBlank(LINEPTR line, PATTERNPTR blankPatternProgram);
STATIC BOOL parseBoolValue(CONST_STRPTR value, BOOL* outBool);
STATIC BOOL parseIntegerValue(CONST_STRPTR value, LONG* outInt, PATTERNPTR integerProgram);
struct SectionStore
{
SectionMap map;
SectionArray array;
// here so we only create them once not each line
PATTERNPTR sectionPatternProgram;
PATTERNPTR variablePatternProgram;
PATTERNPTR blankPatternProgram;
PATTERNPTR integerPatternProgram;
};
SECTIONSTOREPTR SectionStoreNew(VOID)
@ -15,7 +37,10 @@ SECTIONSTOREPTR SectionStoreNew(VOID)
struct SectionStore* result = AllocVec(sizeof(struct SectionStore), MEMF_CLEAR);
result->map = SectionMapNew();
result->array = SectionArrayNew();
result->sectionPatternProgram = PatternNew(RX_SECTION_LINE);
result->variablePatternProgram = PatternNew(RX_VARIABLE_LINE);
result->blankPatternProgram = PatternNew(RX_BLANK_LINE);
result->integerPatternProgram = PatternNew(RX_INTEGER);
return result;
}
@ -26,6 +51,10 @@ VOID SectionStoreFree(SECTIONSTOREPTR abstractSectionStore)
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store->map != NULL ) SectionMapFree( store->map );
if( store->array != NULL ) SectionArrayFree( store->array );
if( store->sectionPatternProgram != NULL ) PatternFree(store->sectionPatternProgram);
if( store->variablePatternProgram != NULL ) PatternFree(store->variablePatternProgram);
if( store->blankPatternProgram != NULL ) PatternFree(store->blankPatternProgram);
if( store->integerPatternProgram != NULL ) PatternFree(store->integerPatternProgram);
FreeVec(store);
}
}
@ -56,3 +85,164 @@ SECTIONPTR SectionStoreGetSection(SECTIONSTOREPTR abstractSectionStore, CONST_ST
return SectionMapGet(store->map, canonicalName);
}
}
SECTIONPTR SectionStoreCurrentSection(SECTIONSTOREPTR abstractSectionStore)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
SECTIONPTR result = NULL;
if( store != NULL && SizeOfArray(store->array) > 0 )
{
result = ArrayBackValue(SECTIONPTR, store->array);
}
return result;
}
VOID SectionStoreAddLine(SECTIONSTOREPTR abstractSectionStore, LINEPTR line)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
// if its a new section, just add it and move on
SECTIONPTR section = parseSection(line, store->sectionPatternProgram);
if( section )
{
SectionStoreAddSection(store, section);
SectionAddSectionLine(section, line);
}
else
{
// if its a variable or blank, parse it and add to current section
VARIABLEPTR variable = NULL;
section = SectionStoreCurrentSection(store);
// if no current section, we're adding variables at the state so create a blank section
if( section == NULL )
{
section = SectionCreateWithName("");
SectionStoreAddSection(store, section);
}
if( variable = parseVariable(line, store->variablePatternProgram) )
{
LineSetInitialVariable(line, variable);
SectionAddLine(section, line);
}
else
{
if( parseBlank(line, store->blankPatternProgram) )
{
SectionAddLine(section, line);
}
else
{
// wasnt a section, a variable or a comment so ignore it or complain
}
}
}
}
}
ULONG SectionStoreSectionCount(SECTIONSTOREPTR abstractSectionStore)
{
ULONG result = 0;
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
return SizeOfArray(store->array);
}
return result;
}
SECTIONPTR SectionStoreSectionAt(SECTIONSTOREPTR abstractSectionStore, ULONG index)
{
SECTIONPTR result = NULL;
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
if( index < SizeOfArray(store->array) )
{
result = SectionArrayValues(store->array)[index];
}
}
return result;
}
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// PRIVATE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
STATIC VARIABLEPTR parseVariable(LINEPTR line, PATTERNPTR variablePatternProgram)
{
VARIABLEPTR result = NULL;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), variablePatternProgram) )
{
result = VariableCreate(StringArrayValues(matches)[1], StringArrayValues(matches)[2]);
StringArrayFree(matches);
}
return result;
}
STATIC SECTIONPTR parseSection(LINEPTR line, PATTERNPTR sectionPatternProgram)
{
SECTIONPTR result = NULL;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), sectionPatternProgram) )
{
if( SizeOfArray(matches) == 3 )
{
result = SectionCreateWithName(StringArrayValues(matches)[1]);
}
else if( SizeOfArray(matches) == 5 )
{
result = SectionCreateWithNameAndSubname(StringArrayValues(matches)[1], StringArrayValues(matches)[3]);
}
StringArrayFree(matches);
}
return result;
}
STATIC BOOL parseBoolValue(CONST_STRPTR value, BOOL* outBool)
{
BOOL result = FALSE;
if( strcmp(value, "yes") == 0 || strcmp(value, "true") == 0 || strcmp(value, "on") == 0 ) {
*outBool = TRUE;
result = TRUE;
}
if( strcmp(value, "no") == 0 || strcmp(value, "false") == 0 || strcmp(value, "off") == 0 ) {
*outBool = FALSE;
result = TRUE;
}
return result;
}
STATIC BOOL parseIntegerValue(CONST_STRPTR value, LONG* outInt, PATTERNPTR integerProgram)
{
BOOL result = FALSE;
StringArray matches = NULL;
if( matches = PatternRun(value, integerProgram) )
{
StringArrayFree(matches);
*outInt = atol(value);
result = TRUE;
}
return result;
}
STATIC BOOL parseBlank(LINEPTR line, PATTERNPTR blankPatternProgram)
{
BOOL result = FALSE;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), blankPatternProgram) )
{
result = TRUE;
StringArrayFree(matches);
}
return result;
}

@ -3,11 +3,16 @@
#include "types.h"
SECTIONPTR SectionStoreGetSection(SECTIONSTOREPTR sectionStore, CONST_STRPTR canonicalName);
SECTIONSTOREPTR SectionStoreNew(VOID);
VOID SectionStoreFree(SECTIONSTOREPTR sectionStore);
VOID SectionStoreAddSection(SECTIONSTOREPTR sectionStore, SECTIONPTR section);
SECTIONPTR SectionStoreCurrentSection(SECTIONSTOREPTR sectionStore);
SECTIONPTR SectionStoreGetSection(SECTIONSTOREPTR sectionStore, CONST_STRPTR canonicalName);
SECTIONSTOREPTR SectionStoreNew(VOID);
VOID SectionStoreAddLine(SECTIONSTOREPTR sectionStore, LINEPTR line);
ULONG SectionStoreSectionCount(SECTIONSTOREPTR sectionStore);
SECTIONPTR SectionStoreSectionAt(SECTIONSTOREPTR sectionStore, ULONG index);
VOID SectionStoreFree(SECTIONSTOREPTR sectionStore);
#endif

@ -14,11 +14,11 @@ LIBS = lib:sc.lib lib:amiga.lib lib:debug.lib
$(NAME) : main.o configmodel.o sectionstore.o cregex/cregex.lib containers/containers.lib
slink lib:c.o main.o configmodel.o sectionstore.o to $(NAME) noicons lib $(LIBS) cregex/cregex.lib containers/containers.lib $(LFLAGS)
cregex/cregex.lib : cregex/cregex_compile.o cregex/cregex_parse.o cregex/cregex_vm.o
JOIN cregex/cregex_compile.o cregex/cregex_parse.o cregex/cregex_vm.o AS cregex/cregex.lib
cregex/cregex.lib : cregex/pattern.o cregex/cregex_compile.o cregex/cregex_parse.o cregex/cregex_vm.o
JOIN cregex/pattern.o cregex/cregex_compile.o cregex/cregex_parse.o cregex/cregex_vm.o AS cregex/cregex.lib
containers/containers.lib : containers/stringarray.o containers/linearray.o containers/linemap.o containers/sectionarray.o containers/sectionmap.o
JOIN containers/stringarray.o containers/linearray.o containers/linemap.o containers/sectionarray.o containers/sectionmap.o AS containers/containers.lib
containers/containers.lib : containers/stringarray.o containers/linearray.o containers/sectionarray.o containers/sectionmap.o
JOIN containers/stringarray.o containers/linearray.o containers/sectionarray.o containers/sectionmap.o AS containers/containers.lib
clean:
delete \#?.o $(NAME) ALL QUIET
@ -30,14 +30,15 @@ cleanlibs:
main.o : main.c
configmodel.o : configmodel.c configmodel.h types.h
configregex.o : configregex.c configregex.h types.h
sectionstore.o : sectionstore.c sectionstore.h types.h
cregex/cregex_compile.o : cregex/cregex_compile.c cregex/cregex.h
cregex/cregex_parse.o : cregex/cregex_parse.c cregex/cregex.h
cregex/cregex_vm.o : cregex/cregex_vm.c cregex/cregex.h
cregex/pattern.o : cregex/pattern.c cregex/pattern.h cregex/cregex.h
containers/stringarray.o : containers/stringarray.c containers/stringarray.h types.h
containers/linearray.o : containers/linearray.c containers/linearray.h types.h
containers/linemap.o : containers/linemap.c containers/linemap.h types.h
containers/sectionarray.o : containers/sectionarray.c containers/sectionarray.h types.h
containers/sectionmap.o : containers/sectionmap.c containers/sectionmap.h types.h

@ -3,11 +3,20 @@
#include <exec/types.h>
typedef APTR SECTIONSTOREPTR;
typedef APTR LINEPTR;
typedef APTR SECTIONPTR;
typedef APTR VARIABLEPTR;
typedef APTR CONFIGFILEPTR;
typedef APTR SECTIONSTOREPTR;
typedef APTR PATTERNPTR;
typedef APTR StringArray;
typedef APTR LineArray;
typedef APTR SectionArray;
typedef APTR SectionMap; // a map of string (canonical name) to Section

Loading…
Cancel
Save