mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-02 16:59:03 +00:00
582 lines
13 KiB
C
582 lines
13 KiB
C
#include "lib.h"
|
|
#include "yamlsettings.h"
|
|
|
|
// Private Prototypes
|
|
void InitYamlContext(ctr_yaml_context *ctx);
|
|
int ParseSpecFile(rsf_settings *set, char *path, dname_struct *dname);
|
|
void ProcessYamlString(ctr_yaml_context *ctx);
|
|
void CheckEvent(ctr_yaml_context *ctx);
|
|
|
|
|
|
void BadYamlFormatting(void);
|
|
|
|
// Code
|
|
int GetYamlSettings(user_settings *set)
|
|
{
|
|
memset(&set->common.rsfSet,0,sizeof(rsf_settings));
|
|
int ret = 0;
|
|
if(set->common.rsfPath) {
|
|
FILE *rsf = fopen(set->common.rsfPath,"rb");
|
|
if(!rsf) {
|
|
fprintf(stderr,"[RSF ERROR] Failed to open %s\n",set->common.rsfPath);
|
|
return FAILED_TO_OPEN_FILE;
|
|
}
|
|
fclose(rsf);
|
|
ret = ParseSpecFile(&set->common.rsfSet,set->common.rsfPath, &set->dname);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ParseSpecFile(rsf_settings *set, char *path, dname_struct *dname)
|
|
{
|
|
ctr_yaml_context *ctx = malloc(sizeof(ctr_yaml_context));
|
|
InitYamlContext(ctx);
|
|
|
|
/* Set Specfile Type */
|
|
|
|
/* Create the Parser object. */
|
|
yaml_parser_initialize(&ctx->parser);
|
|
|
|
/* Set a file input. */
|
|
FILE *input = fopen(path,"rb");
|
|
yaml_parser_set_input_file(&ctx->parser, input);
|
|
|
|
|
|
ctx->dname = dname;
|
|
ctx->IsSequence = false;
|
|
ctx->IsKey = true;
|
|
ctx->prev_event = 0;
|
|
ctx->Level = 0;
|
|
|
|
|
|
/* Read the event sequence. */
|
|
while (!ctx->done) {
|
|
/* Get the next event. */
|
|
GetEvent(ctx);
|
|
if(ctx->error) goto error;
|
|
|
|
/* Proccess Event */
|
|
|
|
|
|
if(EventIsScalar(ctx)){
|
|
EvaluateRSF(set,ctx);
|
|
if(ctx->error) goto error;
|
|
break;
|
|
}
|
|
/*
|
|
if((ctx->event.type == YAML_SEQUENCE_START_EVENT|| ctx->event.type == YAML_MAPPING_START_EVENT) && ctx->prev_event == YAML_SCALAR_EVENT) printf(":\n");
|
|
if(ctx->event.type == YAML_SCALAR_EVENT){
|
|
if(ctx->IsSequence){
|
|
printf(" - %s\n",ctx->event.data.scalar.value);
|
|
}
|
|
else{
|
|
if(!ctx->IsKey) printf(": %s\n",ctx->event.data.scalar.value);
|
|
else printf("%s",ctx->event.data.scalar.value);
|
|
}
|
|
}
|
|
*/
|
|
|
|
/* Finish Event */
|
|
FinishEvent(ctx);
|
|
if(ctx->error) goto error;
|
|
}
|
|
|
|
/* Destroy the Parser object. */
|
|
yaml_parser_delete(&ctx->parser);
|
|
fclose(input);
|
|
return 0;
|
|
|
|
/* On error. */
|
|
error:
|
|
fprintf(stderr,"[RSF ERROR] Error Proccessing RSF file\n");
|
|
|
|
/* Destroy the Parser object. */
|
|
yaml_parser_delete(&ctx->parser);
|
|
fclose(input);
|
|
return ctx->error;
|
|
}
|
|
|
|
void InitYamlContext(ctr_yaml_context *ctx)
|
|
{
|
|
memset(ctx,0,sizeof(ctr_yaml_context));
|
|
}
|
|
|
|
void ProcessYamlString(ctr_yaml_context *ctx)
|
|
{
|
|
if(ctx->string)
|
|
{
|
|
free(ctx->string);
|
|
ctx->string = NULL;
|
|
}
|
|
|
|
if(!ctx->event.data.scalar.value)
|
|
return;
|
|
|
|
char *rawStr = (char*)ctx->event.data.scalar.value;
|
|
int rawStrLen = strlen(rawStr);
|
|
int procStrLen = 0;
|
|
|
|
char *subStart = NULL;
|
|
char *subEnd = NULL;
|
|
char *pos = rawStr;
|
|
char *end = (rawStr+rawStrLen);
|
|
while(pos < end)
|
|
{
|
|
// Find substution syntax in string
|
|
subStart = strstr(pos,"$(");
|
|
if(!subStart)
|
|
{
|
|
procStrLen += (end - pos);
|
|
break;
|
|
}
|
|
|
|
// Check For errors
|
|
if((end - subStart) <= 3) // Valid use of substitution syntax is not possible
|
|
{
|
|
ctx->error = true;
|
|
return;
|
|
}
|
|
|
|
subEnd = strstr((subStart+2),")");
|
|
|
|
if(!subEnd) // no closing bracket
|
|
{
|
|
ctx->error = true;
|
|
return;
|
|
}
|
|
|
|
// Add length of string not accounted for
|
|
procStrLen += (int)(subStart - pos);
|
|
|
|
// Get Length Of substitution key
|
|
char *subName = (subStart+2);
|
|
int subNameLen = (int)((subEnd - subStart) - 2);
|
|
|
|
// Add length of substitutiion value
|
|
for(u32 i = 0; i < ctx->dname->u_items; i++){
|
|
char *testSubName = ctx->dname->items[i].name;
|
|
int testSubNameLen = strlen(testSubName);
|
|
char *testSubValue = ctx->dname->items[i].value;
|
|
int testSubValueLen = strlen(testSubValue);
|
|
|
|
if(testSubNameLen != subNameLen)
|
|
continue;
|
|
if(strncmp(testSubName,subName,subNameLen) != 0)
|
|
continue;
|
|
|
|
procStrLen += testSubValueLen;
|
|
break;
|
|
}
|
|
|
|
// Increment pos
|
|
pos = (subEnd + 1);
|
|
}
|
|
|
|
// Allocate memory for processed string
|
|
ctx->string = calloc(procStrLen+1,sizeof(char));
|
|
char *procStr = ctx->string;
|
|
|
|
pos = rawStr;
|
|
end = (rawStr+rawStrLen);
|
|
while(pos < end)
|
|
{
|
|
// Find substution syntax in string
|
|
subStart = strstr(pos,"$(");
|
|
if(!subStart)
|
|
{
|
|
strncat(procStr,pos,(end - pos));
|
|
break;
|
|
}
|
|
|
|
// Check For errors
|
|
if((end - subStart) <= 3) // Valid use of substitution syntax is not possible
|
|
{
|
|
ctx->error = true;
|
|
return;
|
|
}
|
|
|
|
subEnd = strstr((subStart+2),")");
|
|
|
|
if(!subEnd) // no closing bracket
|
|
{
|
|
ctx->error = true;
|
|
return;
|
|
}
|
|
|
|
// Add length of string not accounted for
|
|
strncat(procStr,pos,(subStart - pos));
|
|
|
|
// Get Length Of substitution key
|
|
char *subName = (subStart+2);
|
|
int subNameLen = (int)((subEnd - subStart) - 2);
|
|
|
|
// Add length of substitutiion value
|
|
for(u32 i = 0; i < ctx->dname->u_items; i++){
|
|
char *testSubName = ctx->dname->items[i].name;
|
|
int testSubNameLen = strlen(testSubName);
|
|
char *testSubValue = ctx->dname->items[i].value;
|
|
int testSubValueLen = strlen(testSubValue);
|
|
|
|
if(testSubNameLen != subNameLen)
|
|
continue;
|
|
if(strncmp(testSubName,subName,subNameLen) != 0)
|
|
continue;
|
|
|
|
strncat(procStr,testSubValue,testSubValueLen);
|
|
break;
|
|
}
|
|
|
|
// Increment pos
|
|
pos = (subEnd + 1);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
char *GetYamlString(ctr_yaml_context *ctx)
|
|
{
|
|
return ctx->string;
|
|
}
|
|
|
|
|
|
u32 GetYamlStringSize(ctr_yaml_context *ctx)
|
|
{
|
|
return strlen(GetYamlString(ctx)); // can't read size from yaml, as string may have been intercepted
|
|
}
|
|
|
|
void GetEvent(ctr_yaml_context *ctx)
|
|
{
|
|
if (!yaml_parser_parse(&ctx->parser, &ctx->event)){
|
|
ctx->error = YAML_API_ERROR;
|
|
return;
|
|
}
|
|
CheckEvent(ctx);
|
|
}
|
|
|
|
void CheckEvent(ctr_yaml_context *ctx)
|
|
{
|
|
switch(ctx->event.type){
|
|
case YAML_SCALAR_EVENT:
|
|
ProcessYamlString(ctx);
|
|
break;
|
|
case YAML_SEQUENCE_START_EVENT:
|
|
ctx->IsSequence = true;
|
|
ctx->IsKey = true;
|
|
ctx->Level++;
|
|
//printf("[LEVEL] %d\n",ctx->Level);
|
|
break;
|
|
case YAML_SEQUENCE_END_EVENT:
|
|
ctx->IsSequence = false;
|
|
ctx->IsKey = true;
|
|
ctx->Level--;
|
|
//printf("[LEVEL] %d\n",ctx->Level);
|
|
break;
|
|
case YAML_MAPPING_START_EVENT:
|
|
ctx->IsKey = true;
|
|
ctx->Level++;
|
|
//printf("[LEVEL] %d\n",ctx->Level);
|
|
break;
|
|
case YAML_MAPPING_END_EVENT:
|
|
ctx->IsKey = true;
|
|
ctx->Level--;
|
|
//printf("[LEVEL] %d\n",ctx->Level);
|
|
break;
|
|
case YAML_DOCUMENT_END_EVENT:
|
|
case YAML_STREAM_END_EVENT:
|
|
ctx->done = true;
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void FinishEvent(ctr_yaml_context *ctx)
|
|
{
|
|
if(ctx->event.type == YAML_SCALAR_EVENT) {
|
|
if(!ctx->IsSequence){
|
|
ctx->IsKey = !ctx->IsKey;
|
|
//if(!ctx->IsKey)ctx->IsKey = true;
|
|
//else ctx->IsKey = false;
|
|
}
|
|
if(ctx->string){
|
|
free(ctx->string);
|
|
ctx->string = NULL;
|
|
}
|
|
}
|
|
|
|
ctx->prev_event = ctx->event.type;
|
|
yaml_event_delete(&ctx->event);
|
|
}
|
|
|
|
bool EventIsScalar(ctr_yaml_context *ctx)
|
|
{
|
|
return (ctx->event.type == YAML_SCALAR_EVENT);
|
|
}
|
|
|
|
bool EventIsMappingStart(ctr_yaml_context *ctx)
|
|
{
|
|
return (ctx->event.type == YAML_MAPPING_START_EVENT);
|
|
}
|
|
|
|
bool EventIsMappingEnd(ctr_yaml_context *ctx)
|
|
{
|
|
return (ctx->event.type == YAML_MAPPING_END_EVENT);
|
|
}
|
|
|
|
bool EventIsSequenceStart(ctr_yaml_context *ctx)
|
|
{
|
|
return (ctx->event.type == YAML_SEQUENCE_START_EVENT);
|
|
}
|
|
|
|
bool EventIsSequenceEnd(ctr_yaml_context *ctx)
|
|
{
|
|
return (ctx->event.type == YAML_SEQUENCE_END_EVENT);
|
|
}
|
|
|
|
bool CheckSequenceEvent(ctr_yaml_context *ctx)
|
|
{
|
|
GetEvent(ctx);
|
|
if(!EventIsSequenceStart(ctx)){
|
|
FinishEvent(ctx);
|
|
//fprintf(stderr,"[-] Bad formatting in Spec file (Expected Sequence)\n");
|
|
//ctx->error = YAML_BAD_FORMATTING;
|
|
return false;
|
|
}
|
|
FinishEvent(ctx);
|
|
return true;
|
|
}
|
|
|
|
bool CheckMappingEvent(ctr_yaml_context *ctx)
|
|
{
|
|
GetEvent(ctx);
|
|
if(!EventIsMappingStart(ctx)){
|
|
FinishEvent(ctx);
|
|
//fprintf(stderr,"[-] Bad formatting in Spec file (Expected Mapping)\n");
|
|
//ctx->error = YAML_BAD_FORMATTING;
|
|
return false;
|
|
}
|
|
FinishEvent(ctx);
|
|
return true;
|
|
}
|
|
|
|
void BadYamlFormatting(void)
|
|
{
|
|
fprintf(stderr,"[-] Bad formatting in Spec file\n");
|
|
}
|
|
|
|
|
|
bool cmpYamlValue(char *string,ctr_yaml_context *ctx)
|
|
{
|
|
return (strcmp(GetYamlString(ctx),string) == 0);
|
|
}
|
|
|
|
bool casecmpYamlValue(char *string,ctr_yaml_context *ctx)
|
|
{
|
|
return (strcasecmp(GetYamlString(ctx),string) == 0);
|
|
}
|
|
|
|
void SetSimpleYAMLValue(char **dest, char *key, ctr_yaml_context *ctx, u32 size_limit)
|
|
{
|
|
if(*dest){
|
|
fprintf(stderr,"[RSF ERROR] Item '%s' is already set\n",key);
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return;
|
|
}
|
|
|
|
GetEvent(ctx);
|
|
if(ctx->error || ctx->done) return;
|
|
if(!EventIsScalar(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return;
|
|
}
|
|
if(!GetYamlStringSize(ctx)) return;
|
|
|
|
u32 size = GetYamlStringSize(ctx);
|
|
if(size > size_limit && size_limit) size = size_limit;
|
|
|
|
|
|
char *tmp = *dest;
|
|
tmp = malloc(size+2);
|
|
if(!tmp) {
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return;
|
|
}
|
|
memset(tmp,0,size+2);
|
|
memcpy(tmp,GetYamlString(ctx),size);
|
|
|
|
//printf("Setting %s to %s (size of %d)\n",key,GetYamlString(ctx),size);
|
|
//printf("Check: %s & %x\n",tmp,tmp);
|
|
*dest = tmp;
|
|
|
|
}
|
|
|
|
bool SetBoolYAMLValue(char *key, ctr_yaml_context *ctx)
|
|
{
|
|
GetEvent(ctx);
|
|
if(ctx->error || ctx->done) return false;
|
|
if(!EventIsScalar(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return false;
|
|
}
|
|
if(!GetYamlStringSize(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return false;
|
|
}
|
|
|
|
if(casecmpYamlValue("true",ctx)) return true;
|
|
if(casecmpYamlValue("false",ctx)) return false;
|
|
|
|
fprintf(stderr,"[RSF ERROR] Invalid '%s'\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return false;
|
|
|
|
}
|
|
|
|
u32 SetYAMLSequence(char ***dest, char *key, ctr_yaml_context *ctx)
|
|
{
|
|
if(*dest){
|
|
fprintf(stderr,"[RSF ERROR] %s already set\n",key);
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
|
|
u32 ActualCount = 0;
|
|
u32 SlotCount = 0;
|
|
char **tmp = *dest;
|
|
if(!CheckSequenceEvent(ctx)) return 0;
|
|
SlotCount = 10;
|
|
tmp = malloc((SlotCount+1)*sizeof(char*));
|
|
if(!tmp){
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
memset(tmp,0,(SlotCount+1)*sizeof(char*));
|
|
GetEvent(ctx);
|
|
if(ctx->error || ctx->done) return 0;
|
|
if(!EventIsScalar(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return 0;
|
|
}
|
|
|
|
|
|
if(!GetYamlStringSize(ctx)) return 0;
|
|
u32 InitLevel = ctx->Level;
|
|
while(ctx->Level == InitLevel){
|
|
if(ctx->error || ctx->done) return 0;
|
|
tmp[ActualCount] = malloc(GetYamlStringSize(ctx)+1);
|
|
memset(tmp[ActualCount],0,GetYamlStringSize(ctx)+1);
|
|
memcpy(tmp[ActualCount],GetYamlString(ctx),GetYamlStringSize(ctx));
|
|
ActualCount++;
|
|
if(ActualCount >= SlotCount){ // if Exceeding Ptr capacity, expand buffer
|
|
SlotCount = SlotCount*2;
|
|
/*
|
|
char **tmp1 = malloc((SlotCount+1)*sizeof(char*)); // allocate new buffer
|
|
if(!tmp1){
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
memset(tmp1,0,(SlotCount+1)*sizeof(char*));
|
|
for(u32 i = 0; i < ActualCount; i++) tmp1[i] = tmp[i]; // Transfer ptrs
|
|
free(tmp); // free original buffer
|
|
tmp = tmp1; // transfer main ptr
|
|
*/
|
|
tmp = realloc(tmp,(SlotCount+1)*sizeof(char*));
|
|
if(!tmp){
|
|
ctx->error = true;
|
|
return 0;
|
|
}
|
|
}
|
|
FinishEvent(ctx);
|
|
GetEvent(ctx);
|
|
}
|
|
FinishEvent(ctx);
|
|
*dest = tmp; // Give main ptr to location
|
|
return ActualCount++; // return number of strings
|
|
}
|
|
|
|
u32 SetYAMLSequenceFromMapping(char ***dest, char *key, ctr_yaml_context *ctx, bool StoreKey)
|
|
{
|
|
if(*dest){
|
|
fprintf(stderr,"[RSF ERROR] %s already set\n",key);
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
|
|
u32 ActualCount = 0;
|
|
u32 SlotCount = 0;
|
|
char **tmp = *dest;
|
|
if(!CheckMappingEvent(ctx)) return 0;
|
|
SlotCount = 10;
|
|
tmp = malloc((SlotCount+1)*sizeof(char*));
|
|
if(!tmp){
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
memset(tmp,0,(SlotCount+1)*sizeof(char*));
|
|
GetEvent(ctx);
|
|
if(ctx->error || ctx->done) return 0;
|
|
if(!EventIsScalar(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return 0;
|
|
}
|
|
|
|
|
|
if(!GetYamlStringSize(ctx)) return 0;
|
|
u32 InitLevel = ctx->Level;
|
|
while(ctx->Level == InitLevel){
|
|
if(ctx->error || ctx->done) return 0;
|
|
if(ctx->IsKey == StoreKey){
|
|
tmp[ActualCount] = malloc(GetYamlStringSize(ctx)+1);
|
|
memset(tmp[ActualCount],0,GetYamlStringSize(ctx)+1);
|
|
memcpy(tmp[ActualCount],GetYamlString(ctx),GetYamlStringSize(ctx));
|
|
ActualCount++;
|
|
if(ActualCount >= SlotCount){ // if Exceeding Ptr capacity, expand buffer
|
|
SlotCount = SlotCount*2;
|
|
char **tmp1 = malloc((SlotCount+1)*sizeof(char*)); // allocate new buffer
|
|
if(!tmp1){
|
|
ctx->error = YAML_MEM_ERROR;
|
|
return 0;
|
|
}
|
|
memset(tmp1,0,(SlotCount+1)*sizeof(char*));
|
|
for(u32 i = 0; i < ActualCount; i++) tmp1[i] = tmp[i]; // Transfer ptrs
|
|
free(tmp); // free original buffer
|
|
tmp = tmp1; // transfer main ptr
|
|
}
|
|
}
|
|
FinishEvent(ctx);
|
|
GetEvent(ctx);
|
|
}
|
|
FinishEvent(ctx);
|
|
*dest = tmp; // Give main ptr to location
|
|
return ActualCount++; // return number of strings
|
|
}
|
|
|
|
/*
|
|
void SkipYAMLGroup(ctr_yaml_context *ctx)
|
|
{
|
|
FinishEvent(ctx);
|
|
GetEvent(ctx);
|
|
if(!EventIsMappingStart(ctx) && !EventIsSequenceStart(ctx) && EventIsScalar(ctx)) return;
|
|
FinishEvent(ctx);
|
|
GetEvent(ctx);
|
|
|
|
if(ctx->error || ctx->done) return;
|
|
if(!EventIsScalar(ctx)){
|
|
fprintf(stderr,"[RSF ERROR] Format error\n");
|
|
ctx->error = YAML_BAD_FORMATTING;
|
|
return;
|
|
}
|
|
if(!GetYamlStringSize(ctx)) return;
|
|
u32 InitLevel = ctx->Level;
|
|
while(ctx->Level == InitLevel){
|
|
if(ctx->error || ctx->done) return;
|
|
FinishEvent(ctx);
|
|
GetEvent(ctx);
|
|
}
|
|
FinishEvent(ctx);
|
|
}
|
|
*/ |