|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|