cinera.c: Sanitise Memory

Fixes / Improvements:

•   Switch all growable arrays to use memory_book, rather than realloc()
•   Lift a bunch of hardcoded string lengths and item counts
•   malloc() the MemoryArena rather than calloc(), thus saving 3 MiB
•   Reorganise HMMLToBuffers() to return from one place, the end
•   Print indexing errors in the same style as config errors / warnings

Diagnoses:

•   Identified sources of "non-freed" memory usage and marked them +MEM.
    This may aid future work on further reducing memory / cycle usage.

New config settings:

•   suppress_prompts boolean
This commit is contained in:
Matt Mascarenhas 2020-06-24 13:29:18 +01:00
parent 6da970d48c
commit 2748687839
2 changed files with 2819 additions and 2420 deletions

File diff suppressed because it is too large Load Diff

View File

@ -343,7 +343,7 @@ tokens *
PushTokens(memory_book *TokensList)
{
tokens *This = MakeSpaceInBook(TokensList);
InitBook(&This->Token, sizeof(token), 16, MBT_TOKEN);
This->Token = InitBook(MBT_TOKEN, 16);
This->CurrentLine = 1;
return This;
}
@ -562,6 +562,7 @@ typedef struct
string QueryString;
bool RespectingPrivacy;
bool SuppressingPrompts;
time_t PrivacyCheckInterval;
uint8_t LogLevel;
@ -648,7 +649,8 @@ Tokenise(memory_book *TokensList, string Path)
Advancement = 2;
T.Type = TOKEN_NULL;
string Char = { .Base = B->Ptr, .Length = 2 };
ConfigError(Result->File.Path, Result->CurrentLine, S_WARNING, "Mismatched closing multiline comment marker: ", &Char);
string Filepath = Wrap0(Result->File.Path);
ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Mismatched closing multiline comment marker: ", &Char);
}
else if(!StringsDifferS(TokenStrings[TOKEN_DOUBLEQUOTE], B))
{
@ -730,13 +732,14 @@ Tokenise(memory_book *TokensList, string Path)
T.Type = TOKEN_NULL;
string Char = GetUTF8Character(B->Ptr, B->Size - (B->Ptr - B->Location));
Advancement = Char.Length;
string Filepath = Wrap0(Result->File.Path);
if(Char.Base)
{
ConfigError(Result->File.Path, Result->CurrentLine, S_WARNING, "Unhandled character (ignored): ", &Char);
ConfigError(&Filepath, Result->CurrentLine, S_WARNING, "Unhandled character (ignored): ", &Char);
}
else
{
ConfigErrorInt(Result->File.Path, Result->CurrentLine, S_WARNING, "Malformed UTF-8 bytes encountered (skipped): ", Char.Length);
ConfigErrorInt(&Filepath, Result->CurrentLine, S_WARNING, "Malformed UTF-8 bytes encountered (skipped): ", Char.Length);
}
}
@ -838,7 +841,7 @@ PushTypeSpec(memory_book *TypeSpecs, config_identifier_id ID, bool IsPermeable)
//PrintFunctionName("PushTypeSpec()");
config_type_spec *Result = MakeSpaceInBook(TypeSpecs);
Result->ID = ID;
InitBook(&Result->Field, sizeof(config_type_field), 4, MBT_CONFIG_TYPE_FIELD);
Result->Field = InitBook(MBT_CONFIG_TYPE_FIELD, 4);
Result->Permeable = IsPermeable;
return Result;
}
@ -858,8 +861,7 @@ _memory_book(config_type_specs)
InitTypeSpecs(void)
{
//PrintFunctionName("InitTypeSpecs()");
memory_book Result = {};
InitBook(&Result, sizeof(config_type_spec), 16, MBT_CONFIG_TYPE_SPEC);
memory_book Result = InitBook(MBT_CONFIG_TYPE_SPEC, 16);
config_type_spec *Root = PushTypeSpec(&Result, IDENT_NULL, FALSE);
PushTypeSpecField(Root, FT_STRING, IDENT_ASSETS_ROOT_DIR, TRUE);
@ -909,6 +911,7 @@ InitTypeSpecs(void)
PushTypeSpecField(Root, FT_BOOLEAN, IDENT_DENY_BESPOKE_TEMPLATES, TRUE);
PushTypeSpecField(Root, FT_BOOLEAN, IDENT_IGNORE_PRIVACY, TRUE);
PushTypeSpecField(Root, FT_BOOLEAN, IDENT_SINGLE_BROWSER_TAB, TRUE);
PushTypeSpecField(Root, FT_BOOLEAN, IDENT_SUPPRESS_PROMPTS, TRUE);
PushTypeSpecField(Root, FT_NUMBER, IDENT_PRIVACY_CHECK_INTERVAL, TRUE);
PushTypeSpecField(Root, FT_SCOPE, IDENT_INCLUDE, FALSE);
PushTypeSpecField(Root, FT_SCOPE, IDENT_MEDIUM, FALSE);
@ -1170,7 +1173,7 @@ SetTypeSpec(scope_tree *Type, memory_book *TypeSpecs)
//PrintTypeSpec(Spec);
Type->TypeSpec.ID = Spec->ID;
Type->TypeSpec.Permeable = Spec->Permeable;
InitBook(&Type->TypeSpec.Field, sizeof(config_type_field), 4, MBT_CONFIG_TYPE_FIELD);
Type->TypeSpec.Field = InitBook(MBT_CONFIG_TYPE_FIELD, 4);
for(int i = 0; i < Spec->Field.ItemCount; ++i)
{
config_type_field *Src = GetPlaceInBook(&Spec->Field, i);
@ -1537,10 +1540,10 @@ PushBoolPair(scope_tree *Parent, config_bool_pair *B)
void
InitScopeBooks(scope_tree *Scope)
{
InitBook(&Scope->Trees, sizeof(scope_tree), 4, MBT_CONFIG_PAIR);
InitBook(&Scope->Pairs, sizeof(config_pair), 4, MBT_CONFIG_PAIR);
InitBook(&Scope->IntPairs, sizeof(config_int_pair), 4, MBT_CONFIG_INT_PAIR);
InitBook(&Scope->BoolPairs, sizeof(config_bool_pair), 4, MBT_CONFIG_BOOL_PAIR);
Scope->Trees = InitBook(MBT_SCOPE_TREE, 4);
Scope->Pairs = InitBook(MBT_CONFIG_PAIR, 4);
Scope->IntPairs = InitBook(MBT_CONFIG_INT_PAIR, 4);
Scope->BoolPairs = InitBook(MBT_CONFIG_BOOL_PAIR, 4);
}
scope_tree *
@ -1816,7 +1819,7 @@ PushRule(config_include_rules *R, config_identifier_id ID)
}
void
ParseRuleString(char *Filename, memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, config_include_rules *Rules, token *RuleString)
ParseRuleString(string *Filename, memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, config_include_rules *Rules, token *RuleString)
{
int i = SkipWhitespaceS(&RuleString->Content, 0);
config_type_field *Field = 0;
@ -1908,6 +1911,7 @@ ParseIncludeRules(memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, toke
++T->CurrentIndex;
for(; T->CurrentIndex < T->Token.ItemCount;)
{
string Filepath = Wrap0(T->File.Path);
if(TokenIs(T, TOKEN_IDENTIFIER))
{
if(TokenEquals(T, "allow"))
@ -1916,7 +1920,7 @@ ParseIncludeRules(memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, toke
{
FreeBook(&Rules->ID);
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Mixture of allow and deny identifiers in \"include\" scope", 0);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Mixture of allow and deny identifiers in \"include\" scope", 0);
return DepartIncludeAssignment(T, IncludeIdentifierTokenIndex) ? RC_SCHEME_MIXTURE : RC_SYNTAX_ERROR;
}
Rules->Scheme = CRT_ALLOW;
@ -1927,7 +1931,7 @@ ParseIncludeRules(memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, toke
{
FreeBook(&Rules->ID);
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Mixture of allow and deny identifiers in \"include\" scope", 0);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Mixture of allow and deny identifiers in \"include\" scope", 0);
return DepartIncludeAssignment(T, IncludeIdentifierTokenIndex) ? RC_SCHEME_MIXTURE : RC_SYNTAX_ERROR;
}
Rules->Scheme = CRT_DENY;
@ -1935,7 +1939,7 @@ ParseIncludeRules(memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, toke
else
{
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Invalid identifier in \"include\" scope: ", &This->Content);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Invalid identifier in \"include\" scope: ", &This->Content);
fprintf(stderr,
" Valid identifiers:\n"
" allow\n"
@ -1947,7 +1951,7 @@ ParseIncludeRules(memory_book *TypeSpecs, config_type_spec *ParentTypeSpec, toke
if(!ExpectToken(T, TOKEN_ASSIGN, 0)) { FreeBook(&Rules->ID); return RC_SYNTAX_ERROR; }
token RuleString = {};
if(!ExpectToken(T, TOKEN_STRING, &RuleString)) { FreeBook(&Rules->ID); return RC_SYNTAX_ERROR; }
ParseRuleString(T->File.Path, TypeSpecs, ParentTypeSpec, Rules, &RuleString);
ParseRuleString(&Filepath, TypeSpecs, ParentTypeSpec, Rules, &RuleString);
if(!ExpectToken(T, TOKEN_SEMICOLON, 0)) { FreeBook(&Rules->ID); return RC_SYNTAX_ERROR; }
}
else if(TokenIs(T, TOKEN_CLOSE_BRACE))
@ -2051,6 +2055,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
scope_tree *Parent = Tree;
for(T->CurrentIndex = 0; T->CurrentIndex < T->Token.ItemCount;)
{
string Filepath = Wrap0(T->File.Path);
if(TokenIs(T, TOKEN_IDENTIFIER))
{
config_type_field *Field = CurrentFieldIsInSpec(&Parent->TypeSpec, T);
@ -2061,7 +2066,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
if(Field->IsSetLocally && Field->Singleton)
{
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Field already set: ", &This->Content);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Field already set: ", &This->Content);
}
// NOTE(matt): If we get rid of FT_BARE, then the ++T->CurrentIndex that all cases perform could happen
// right here
@ -2098,7 +2103,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
BoolPair.Position.LineNumber = Value.LineNumber;
if(!ExpectToken(T, TOKEN_SEMICOLON, 0)) { FreeScopeTree(Tree); return 0; }
bool Bool = GetBoolFromString(T->File.Path, &Value);
bool Bool = GetBoolFromString(&Filepath, &Value);
if(Bool != -1)
{
BoolPair.Value = Bool;
@ -2128,7 +2133,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
if(Field->ID == IDENT_NUMBERING_SCHEME)
{
numbering_scheme NumberingScheme = GetNumberingSchemeFromString(T->File.Path, &Value);
numbering_scheme NumberingScheme = GetNumberingSchemeFromString(&Filepath, &Value);
if(NumberingScheme != NS_COUNT)
{
IntPair.Value = NumberingScheme;
@ -2146,7 +2151,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
}
else if(Field->ID == IDENT_LOG_LEVEL)
{
log_level LogLevel = GetLogLevelFromString(T->File.Path, &Value);
log_level LogLevel = GetLogLevelFromString(&Filepath, &Value);
if(LogLevel != LOG_COUNT)
{
IntPair.Value = LogLevel;
@ -2164,7 +2169,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
}
else if(Field->ID == IDENT_GENRE)
{
genre Genre = GetGenreFromString(T->File.Path, &Value);
genre Genre = GetGenreFromString(&Filepath, &Value);
if(Genre != GENRE_COUNT)
{
IntPair.Value = Genre;
@ -2182,7 +2187,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
}
else if(Field->ID == IDENT_ICON_TYPE)
{
icon_type IconType = GetIconTypeFromString(T->File.Path, &Value);
icon_type IconType = GetIconTypeFromString(&Filepath, &Value);
if(IconType != IT_COUNT)
{
IntPair.Value = IconType;
@ -2200,7 +2205,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
}
else if(Field->ID == IDENT_ART_VARIANTS || Field->ID == IDENT_ICON_VARIANTS)
{
int64_t ArtVariants = ParseArtVariantsString(T->File.Path, &Value);
int64_t ArtVariants = ParseArtVariantsString(&Filepath, &Value);
if(ArtVariants != -1)
{
IntPair.Value = ArtVariants;
@ -2268,7 +2273,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
{
int IncludePathTokenIndex = T->CurrentIndex - 1;
config_include_rules Rules = {};
InitBook(&Rules.ID, sizeof(config_identifier_id), 4, MBT_CONFIG_IDENTIFIER_ID);
Rules.ID = InitBook(MBT_CONFIG_IDENTIFIER_ID, 4);
switch(ParseIncludeRules(TypeSpecs, &Parent->TypeSpec, T, &Rules))
{
case RC_SUCCESS:
@ -2304,7 +2309,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
else
{
token *This = GetPlaceInBook(&T->Token, IncludePathTokenIndex);
ConfigFileIncludeError(T->File.Path, This->LineNumber, Wrap0(IncludePath));
ConfigFileIncludeError(&Filepath, This->LineNumber, Wrap0(IncludePath));
}
Free(IncludePath);
} break;
@ -2392,14 +2397,14 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
else
{
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Field not allowed: ", &This->Content);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Field not allowed: ", &This->Content);
DepartAssignment(T);
}
}
else
{
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_WARNING, "Invalid field: ", &This->Content);
ConfigError(&Filepath, This->LineNumber, S_WARNING, "Invalid field: ", &This->Content);
if(!DepartAssignment(T))
{
FreeScopeTree(Tree);
@ -2412,7 +2417,7 @@ ScopeTokens(scope_tree *Tree, memory_book *TokensList, tokens *T, memory_book *T
if(!Parent->Parent)
{
token *This = GetPlaceInBook(&T->Token, T->CurrentIndex);
ConfigError(T->File.Path, This->LineNumber, S_ERROR, "Syntax error: Unpaired closing brace", 0);
ConfigError(&Filepath, This->LineNumber, S_ERROR, "Syntax error: Unpaired closing brace", 0);
FreeScopeTree(Tree);
return 0;
}
@ -2552,7 +2557,8 @@ GetPerson(config *C, resolution_errors *E, config_pair *PersonID)
if(!GetError(E, S_WARNING, &PersonID->Position, IDENT_PERSON))
{
ConfigError(PersonID->Position.Filename, PersonID->Position.LineNumber, S_WARNING, "Could not find person: ", &PersonID->Value);
string Filepath = Wrap0(PersonID->Position.Filename);
ConfigError(&Filepath, PersonID->Position.LineNumber, S_WARNING, "Could not find person: ", &PersonID->Value);
PushError(E, S_WARNING, &PersonID->Position, IDENT_PERSON);
}
return 0;
@ -2562,8 +2568,7 @@ string
DeriveLineageOfProject(config *C, scope_tree *Project)
{
string Result = {};
memory_book StringList = {};
InitBookOfPointers(&StringList, 4, MBT_STRING_PTR);
memory_book StringList = InitBookOfPointers(MBT_STRING_PTR, 4);
if(Project)
{
string **Writer = MakeSpaceInBook(&StringList);
@ -2642,6 +2647,7 @@ string
ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_identifier_id Variable, token_position *Position)
{
string Result = {};
string Filepath = Wrap0(Position->Filename);
switch(Variable)
{
case IDENT_LINEAGE:
@ -2655,7 +2661,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
string This = Wrap0(ConfigIdentifiers[Variable].String);
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
PushError(E, S_WARNING, Position, Variable);
}
}
@ -2671,7 +2677,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
string This = Wrap0(ConfigIdentifiers[Variable].String);
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
PushError(E, S_WARNING, Position, Variable);
}
}
@ -2691,7 +2697,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
string This = Wrap0(ConfigIdentifiers[Variable].String);
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
PushError(E, S_WARNING, Position, Variable);
}
}
@ -2714,7 +2720,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
{
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Owner set, but the person does not exist: ", &Pair->Value);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Owner set, but the person does not exist: ", &Pair->Value);
PushError(E, S_WARNING, Position, Variable);
}
Processed = TRUE;
@ -2725,7 +2731,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
{
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "No owner set", 0);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "No owner set", 0);
PushError(E, S_WARNING, Position, Variable);
}
}
@ -2749,7 +2755,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
string This = Wrap0(ConfigIdentifiers[Variable].String);
if(!GetError(E, S_WARNING, Position, Variable))
{
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Variable could not be resolved: ", &This);
PushError(E, S_WARNING, Position, Variable);
}
}
@ -2759,7 +2765,7 @@ ResolveLocalVariable(config *C, resolution_errors *E, scope_tree *Scope, config_
if(!GetError(E, S_WARNING, Position, Variable))
{
string This = Wrap0(ConfigIdentifiers[Variable].String);
ConfigError(Position->Filename, Position->LineNumber, S_WARNING, "Unhandled local variable: ", &This);
ConfigError(&Filepath, Position->LineNumber, S_WARNING, "Unhandled local variable: ", &This);
PushError(E, S_WARNING, Position, Variable);
}
} break;
@ -2916,7 +2922,7 @@ PushVariantUniquely(resolution_errors *E, memory_book *VariantStrings, string Pa
variant_string *NewVariantString = MakeSpaceInBook(VariantStrings);
NewVariantString->Path = Path;
InitBook(&NewVariantString->Variants, sizeof(variant), 4, MBT_VARIANT);
NewVariantString->Variants = InitBook(MBT_VARIANT, 4);
variant *NewVariants = MakeSpaceInBook(&NewVariantString->Variants);
*NewVariants = Variants;
}
@ -3112,7 +3118,7 @@ PushPersonOntoConfig(config *C, resolution_errors *E, config_verifiers *V, scope
}
}
InitBook(&This->Support, sizeof(support), 2, MBT_SUPPORT);
This->Support = InitBook(MBT_SUPPORT, 2);
for(int i = 0; i < PersonTree->Trees.ItemCount; ++i)
{
scope_tree *ThisSupport = GetPlaceInBook(&PersonTree->Trees, i);
@ -3161,7 +3167,7 @@ void
PushAssociation(config_string_associations *HMMLDirs, string *S0, string *S1, project *P)
{
config_string_association *This = MakeSpaceInBook(&HMMLDirs->Associations);
InitBookOfPointers(&This->Projects, 4, MBT_PROJECT_PTR);
This->Projects = InitBookOfPointers(MBT_PROJECT_PTR, 4);
if(S0) { This->String0 = *S0; }
if(S1) { This->String1 = *S1; }
@ -3240,17 +3246,18 @@ SetUniqueHMMLDir(config *C, resolution_errors *E, config_string_associations *HM
void
PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, scope_tree *ProjectTree)
{
InitBook(&P->Medium, sizeof(medium), 8, MBT_MEDIUM);
InitBook(&P->Child, sizeof(project), 8, MBT_PROJECT);
InitBookOfPointers(&P->Indexer, 4, MBT_PERSON_PTR);
InitBookOfPointers(&P->CoHost, 4, MBT_PERSON_PTR);
InitBookOfPointers(&P->Guest, 4, MBT_PERSON_PTR);
P->Medium = InitBook(MBT_MEDIUM, 8);
P->Child = InitBook(MBT_PROJECT, 8);
P->Indexer = InitBookOfPointers(MBT_PERSON_PTR, 4);
P->CoHost = InitBookOfPointers(MBT_PERSON_PTR, 4);
P->Guest = InitBookOfPointers(MBT_PERSON_PTR, 4);
config_string_associations *HMMLDirs = &V->HMMLDirs;
P->ID = ResolveString(C, E, ProjectTree, &ProjectTree->ID, FALSE);
if(P->ID.Length > MAX_PROJECT_ID_LENGTH)
{
ConfigErrorSizing(ProjectTree->ID.Position.Filename, ProjectTree->ID.Position.LineNumber, IDENT_PROJECT, &P->ID, MAX_PROJECT_ID_LENGTH);
string Filepath = Wrap0(ProjectTree->ID.Position.Filename);
ConfigErrorSizing(&Filepath, ProjectTree->ID.Position.LineNumber, IDENT_PROJECT, &P->ID, MAX_PROJECT_ID_LENGTH);
PushError(E, S_ERROR, 0, IDENT_PROJECT);
}
@ -3269,6 +3276,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
for(int i = 0; i < ProjectTree->Pairs.ItemCount; ++i)
{
config_pair *This = GetPlaceInBook(&ProjectTree->Pairs, i);
string Filepath = Wrap0(This->Position.Filename);
switch(This->Key)
{
case IDENT_DEFAULT_MEDIUM:
@ -3290,7 +3298,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
{ P->Theme = ResolveString(C, E, ProjectTree, This, FALSE);
if(P->Theme.Length > MAX_THEME_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->Theme, MAX_THEME_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -3300,7 +3308,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
P->Title = ResolveString(C, E, ProjectTree, This, FALSE);
if(P->Title.Length > MAX_PROJECT_NAME_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->Title, MAX_PROJECT_NAME_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -3317,7 +3325,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
P->BaseDir = StripSlashes(ResolveString(C, E, ProjectTree, This, TRUE), P_ABS);
if(P->BaseDir.Length > MAX_BASE_DIR_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->BaseDir, MAX_BASE_DIR_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -3327,7 +3335,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
P->BaseURL = ResolveString(C, E, ProjectTree, This, FALSE);
if(P->BaseURL.Length > MAX_BASE_URL_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->BaseURL, MAX_BASE_URL_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -3337,7 +3345,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
P->PlayerLocation = StripSlashes(ResolveString(C, E, ProjectTree, This, FALSE), P_REL);
if(P->PlayerLocation.Length > MAX_RELATIVE_PAGE_LOCATION_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->PlayerLocation, MAX_RELATIVE_PAGE_LOCATION_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -3347,7 +3355,7 @@ PushProject(config *C, resolution_errors *E, config_verifiers *V, project *P, sc
P->SearchLocation = StripSlashes(ResolveString(C, E, ProjectTree, This, FALSE), P_REL);
if(P->SearchLocation.Length > MAX_RELATIVE_PAGE_LOCATION_LENGTH)
{
ConfigErrorSizing(This->Position.Filename, This->Position.LineNumber, This->Key,
ConfigErrorSizing(&Filepath, This->Position.LineNumber, This->Key,
&P->SearchLocation, MAX_RELATIVE_PAGE_LOCATION_LENGTH);
PushError(E, S_ERROR, 0, This->Key);
}
@ -4374,18 +4382,18 @@ config_verifiers
InitVerifiers(void)
{
config_verifiers Result = {};
InitBook(&Result.VariantStrings, sizeof(variant_string), 8, MBT_VARIANT_STRING);
Result.VariantStrings = InitBook(MBT_VARIANT_STRING, 8);
Result.HMMLDirs.ID0 = IDENT_HMML_DIR;
InitBook(&Result.HMMLDirs.Associations, sizeof(config_string_association), 8, MBT_CONFIG_STRING_ASSOCIATION);
Result.HMMLDirs.Associations = InitBook(MBT_CONFIG_STRING_ASSOCIATION, 8);
Result.BaseDirAndSearchLocation.ID0 = IDENT_BASE_DIR;
Result.BaseDirAndSearchLocation.ID1 = IDENT_SEARCH_LOCATION;
InitBook(&Result.BaseDirAndSearchLocation.Associations, sizeof(config_string_association), 8, MBT_CONFIG_STRING_ASSOCIATION);
Result.BaseDirAndSearchLocation.Associations = InitBook(MBT_CONFIG_STRING_ASSOCIATION, 8);
Result.BaseDirAndPlayerLocation.ID0 = IDENT_BASE_DIR;
Result.BaseDirAndPlayerLocation.ID1 = IDENT_PLAYER_LOCATION;
InitBook(&Result.BaseDirAndPlayerLocation.Associations, sizeof(config_string_association), 8, MBT_CONFIG_STRING_ASSOCIATION);
Result.BaseDirAndPlayerLocation.Associations = InitBook(MBT_CONFIG_STRING_ASSOCIATION, 8);
return Result;
}
@ -4394,19 +4402,20 @@ ResolveVariables(scope_tree *S)
{
Assert(LOG_COUNT == ArrayCount(LogLevelStrings));
config *Result = calloc(1, sizeof(config));
InitBook(&Result->ResolvedVariables, 1, Kilobytes(1), MBT_STRING);
InitBook(&Result->Person, sizeof(person), 8, MBT_PERSON);
InitBook(&Result->Project, sizeof(project), 8, MBT_PROJECT);
Result->ResolvedVariables = InitBookOfStrings(Kilobytes(1));
Result->Person = InitBook(MBT_PERSON, 8);
Result->Project = InitBook(MBT_PROJECT, 8);
resolution_errors Errors = {};
InitBook(&Errors.Warnings, sizeof(resolution_error), 16, MBT_RESOLUTION_ERROR);
InitBook(&Errors.Errors, sizeof(resolution_error), 16, MBT_RESOLUTION_ERROR);
Errors.Warnings = InitBook(MBT_RESOLUTION_ERROR, 16);
Errors.Errors = InitBook(MBT_RESOLUTION_ERROR, 16);
config_verifiers Verifiers = InitVerifiers();
for(int i = 0; i < S->Pairs.ItemCount; ++i)
{
config_pair *Pair = GetPlaceInBook(&S->Pairs, i);
string Filepath = Wrap0(Pair->Position.Filename);
switch(Pair->Key)
{
case IDENT_DB_LOCATION:
@ -4416,7 +4425,7 @@ ResolveVariables(scope_tree *S)
Result->GlobalSearchDir = StripSlashes(ResolveString(Result, &Errors, S, Pair, TRUE), P_ABS);
if(Result->GlobalSearchDir.Length > MAX_BASE_DIR_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->GlobalSearchDir, MAX_BASE_DIR_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4426,7 +4435,7 @@ ResolveVariables(scope_tree *S)
Result->GlobalSearchURL = StripSlashes(ResolveString(Result, &Errors, S, Pair, TRUE), P_ABS);
if(Result->GlobalSearchURL.Length > MAX_BASE_URL_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->GlobalSearchURL, MAX_BASE_URL_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4440,7 +4449,7 @@ ResolveVariables(scope_tree *S)
Result->GlobalTheme = ResolveString(Result, &Errors, S, Pair, FALSE);
if(Result->GlobalTheme.Length > MAX_THEME_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->GlobalTheme, MAX_THEME_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4450,7 +4459,7 @@ ResolveVariables(scope_tree *S)
Result->AssetsRootDir = StripSlashes(ResolveString(Result, &Errors, S, Pair, TRUE), P_ABS);
if(Result->AssetsRootDir.Length > MAX_ROOT_DIR_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->AssetsRootDir, MAX_ROOT_DIR_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4460,7 +4469,7 @@ ResolveVariables(scope_tree *S)
Result->AssetsRootURL = StripSlashes(ResolveString(Result, &Errors, S, Pair, TRUE), P_ABS);
if(Result->AssetsRootURL.Length > MAX_ROOT_URL_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->AssetsRootURL, MAX_ROOT_URL_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4470,7 +4479,7 @@ ResolveVariables(scope_tree *S)
Result->CSSDir = StripSlashes(ResolveString(Result, &Errors, S, Pair, FALSE), P_REL);
if(Result->CSSDir.Length > MAX_RELATIVE_ASSET_LOCATION_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->CSSDir, MAX_RELATIVE_ASSET_LOCATION_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4480,7 +4489,7 @@ ResolveVariables(scope_tree *S)
Result->ImagesDir = StripSlashes(ResolveString(Result, &Errors, S, Pair, FALSE), P_REL);
if(Result->ImagesDir.Length > MAX_RELATIVE_ASSET_LOCATION_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->ImagesDir, MAX_RELATIVE_ASSET_LOCATION_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4490,7 +4499,7 @@ ResolveVariables(scope_tree *S)
Result->JSDir = StripSlashes(ResolveString(Result, &Errors, S, Pair, FALSE), P_REL);
if(Result->JSDir.Length > MAX_RELATIVE_ASSET_LOCATION_LENGTH)
{
ConfigErrorSizing(Pair->Position.Filename, Pair->Position.LineNumber, Pair->Key,
ConfigErrorSizing(&Filepath, Pair->Position.LineNumber, Pair->Key,
&Result->JSDir, MAX_RELATIVE_ASSET_LOCATION_LENGTH);
PushError(&Errors, S_ERROR, 0, Pair->Key);
}
@ -4517,6 +4526,17 @@ ResolveVariables(scope_tree *S)
}
}
for(int i = 0; i < S->BoolPairs.ItemCount; ++i)
{
config_bool_pair *BoolPair = GetPlaceInBook(&S->BoolPairs, i);
switch(BoolPair->Key)
{
case IDENT_SUPPRESS_PROMPTS:
{ Result->SuppressingPrompts = BoolPair->Value; } break;
default: break;
}
}
for(int i = 0; i < S->Trees.ItemCount; ++i)
{
scope_tree *Tree = GetPlaceInBook(&S->Trees, i);