version 1.2, 2015/04/20 18:10:14
|
version 1.3, 2015/04/20 18:19:56
|
|
|
| |
#include <stdio.h> | #include <stdio.h> |
#include <ctype.h> | #include <ctype.h> |
#include <base/strings.h> |
#include <pal/strings.h> |
#include <base/list.h> | #include <base/list.h> |
#include <base/io.h> |
#include <pal/format.h> |
|
#include <pal/file.h> |
|
#include <base/log.h> |
#include "regfile.h" | #include "regfile.h" |
| |
|
#define REG_INDICATION_CLASS "INDICATIONCLASS" |
|
|
// Parse an identifies of the form "[A-Za-z_][A-Za-z_0-9]*" | // Parse an identifies of the form "[A-Za-z_][A-Za-z_0-9]*" |
static int _ParseIdentifier(char** pOut, char** start, char** end) |
_Return_type_success_(return == 0) |
|
static int _ParseIdentifier(_Inout_ CharPtr* pOut, _Out_ CharPtr* start, _Out_ CharPtr* end) |
{ | { |
char* p = *pOut; | char* p = *pOut; |
| |
/* Skip leading whitespace */ | /* Skip leading whitespace */ |
while (isspace((unsigned char)(*p))) |
while (*p && isspace((unsigned char)(*p))) |
p++; | p++; |
| |
/* Set start of identifier */ | /* Set start of identifier */ |
|
|
return -1; | return -1; |
| |
/* Skip [A-Za-z_0-9] characters */ | /* Skip [A-Za-z_0-9] characters */ |
while (isalnum((unsigned char)(*p)) || *p == '_') |
while (*p && (isalnum((unsigned char)(*p)) || *p == '_')) |
p++; | p++; |
| |
/* Set end of identifier */ | /* Set end of identifier */ |
|
|
} | } |
| |
// Parase class path of the form "CLASS1:CLASS2:CLASS3" | // Parase class path of the form "CLASS1:CLASS2:CLASS3" |
static int _ParseClassPath(char** pOut, char** start, char** end) |
_Return_type_success_(return == 0) |
|
static int _ParseClassPath(_Inout_ CharPtr* pOut, _Out_ CharPtr* start, _Out_ CharPtr* end) |
{ | { |
char* p = *pOut; | char* p = *pOut; |
| |
/* Skip leading whitespace */ | /* Skip leading whitespace */ |
while (isspace((unsigned char)(*p))) |
while (*p && isspace((unsigned char)(*p))) |
p++; | p++; |
| |
/* Set start of identifier */ | /* Set start of identifier */ |
|
|
return -1; | return -1; |
| |
/* Skip [A-Za-z_0-9] characters */ | /* Skip [A-Za-z_0-9] characters */ |
while (isalnum((unsigned char)(*p)) || *p == '_' || *p == ':') |
while (*p && (isalnum((unsigned char)(*p)) || *p == '_' || *p == ':')) |
p++; | p++; |
| |
/* Set end of identifier */ | /* Set end of identifier */ |
|
|
return 0; | return 0; |
} | } |
| |
static int _ExpectChar(char** pOut, char ch) |
_Return_type_success_(return == 0) |
|
static int _ExpectChar(_Inout_ CharPtr* pOut, char ch) |
{ | { |
char* p = *pOut; | char* p = *pOut; |
| |
/* Skip whitespace */ | /* Skip whitespace */ |
while (isspace((unsigned char)(*p))) |
while (*p && isspace((unsigned char)(*p))) |
p++; | p++; |
| |
/* Expect character */ | /* Expect character */ |
|
|
} | } |
| |
// Parse a line of the form 'KEY=VALUE' | // Parse a line of the form 'KEY=VALUE' |
static int _ParseKeyValueLine(char** pOut, char** keyOut, char** valueOut) |
_Return_type_success_(return == 0) |
|
static int _ParseKeyValueLine(_Inout_ CharPtr* pOut, _Out_ CharPtr* keyOut, _Out_ CharPtr* valueOut) |
{ | { |
char* p = *pOut; | char* p = *pOut; |
char* keyEnd; | char* keyEnd; |
|
|
*keyEnd = '\0'; | *keyEnd = '\0'; |
| |
/* Skip whitespace */ | /* Skip whitespace */ |
while (isspace((unsigned char)(*p))) |
while (*p && isspace((unsigned char)(*p))) |
p++; | p++; |
| |
/* Set value */ | /* Set value */ |
|
|
return 0; | return 0; |
} | } |
| |
|
/* |
|
* Parses <value> from `*CLASS=<value>` of the forms from .reg file: |
|
* 1. `<ClassPath>` (Non-Association class) |
|
* 2. `<ClassPath>{<ClassPath>,<ClassPath>}` (Association class) |
|
*/ |
|
_Return_type_success_(return == 0) |
static int _ParseClassValue( | static int _ParseClassValue( |
char** pOut, |
_Inout_ CharPtr* pOut, |
char** nameOut, |
_Out_ CharPtr* nameOut, |
char** refName1Out, |
_Out_ CharPtr* refName1Out, |
char** refName2Out) |
_Out_ CharPtr* refName2Out) |
{ | { |
char* p = *pOut; | char* p = *pOut; |
char* start; | char* start; |
|
|
return -1; | return -1; |
| |
/* Skip whitespace */ | /* Skip whitespace */ |
while (isspace((unsigned char)(*p))) |
while (*p && isspace((unsigned char)(*p))) |
p++; | p++; |
| |
/* If end of line */ | /* If end of line */ |
|
|
return 0; | return 0; |
} | } |
| |
|
|
|
|
|
/* Parse indication class from reg file */ |
|
_Return_type_success_(return == 0) |
|
int ParseIndicationClass( |
|
_Inout_ CharPtr* pOut, |
|
_Inout_ RegFile* self, |
|
_In_opt_z_ char* hosting, |
|
_In_ ProvRegType type) |
|
{ |
|
#ifdef DISABLE_INDICATION |
|
/* Ignore indication classes */ |
|
MI_UNUSED(pOut); |
|
MI_UNUSED(self); |
|
MI_UNUSED(hosting); |
|
MI_UNUSED(type); |
|
return 0; |
|
#else /* ifndef DISABLE_INDICATION */ |
|
char* name = NULL; |
|
char* refName1 = NULL; |
|
char* refName2 = NULL; |
|
RegClass* rc; |
|
|
|
if (_ParseClassValue(pOut, &name, &refName1, &refName2) != 0) |
|
{ |
|
trace_RegFile_ParseIndication_ClassValueFailed(); |
|
return -1; |
|
} |
|
|
|
rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass)); |
|
if (!rc) |
|
{ |
|
trace_RegFile_AllocFailure(); |
|
return -1; |
|
} |
|
|
|
List_Append( |
|
(ListElem**)&self->classesHead, |
|
(ListElem**)&self->classesTail, |
|
(ListElem*)rc); |
|
|
|
if (refName1 || refName2) |
|
{ |
|
trace_RegFile_IndicationClassCannotHaveRefClass(); |
|
return -1; |
|
} |
|
|
|
rc->name = PAL_Strdup(name); |
|
if (!rc->name) |
|
{ |
|
trace_RegFile_OutOfMemory_Name(); |
|
return -1; |
|
} |
|
|
|
if (hosting) |
|
{ |
|
rc->hosting = PAL_Strdup(hosting); |
|
if(!rc->hosting) |
|
{ |
|
trace_RegFile_OutOfMemory_Hosting(); |
|
return -1; |
|
} |
|
} |
|
rc->regtype = type; |
|
return 0; |
|
#endif /* ifndef DISABLE_INDICATION */ |
|
} |
|
|
|
|
RegFile* RegFile_New(const char* path) | RegFile* RegFile_New(const char* path) |
{ | { |
FILE* is; | FILE* is; |
char buf[1024]; |
char buf[MAX_LINE]; |
int foundLibrary = 0; | int foundLibrary = 0; |
char* hosting = NULL; | char* hosting = NULL; |
|
|
RegFile* self = 0; | RegFile* self = 0; |
| |
/* Open the file */ | /* Open the file */ |
is = Fopen(path, "rb"); |
is = File_Open(path, "rb"); |
if (!is) | if (!is) |
return NULL; | return NULL; |
| |
/* Allocate self structure */ | /* Allocate self structure */ |
self = (RegFile*)calloc(1, sizeof(RegFile)); |
self = (RegFile*)PAL_Calloc(1, sizeof(RegFile)); |
if (!self) | if (!self) |
{ | { |
fclose(is); | fclose(is); |
|
|
char* key; | char* key; |
char* value; | char* value; |
| |
|
/* Skip leading whitespace */ |
|
while (*p && isspace((unsigned char)(*p))) |
|
p++; |
|
|
/* Skip comment lines */ | /* Skip comment lines */ |
if (*p == '#') | if (*p == '#') |
continue; | continue; |
|
|
*--end = '\0'; | *--end = '\0'; |
} | } |
| |
/* Skip leading whitespace */ |
|
while (isspace((unsigned char)(*p))) |
|
p++; |
|
|
|
/* Skip blank lines */ | /* Skip blank lines */ |
if (*p == '\0') | if (*p == '\0') |
continue; | continue; |
|
|
if (foundLibrary) | if (foundLibrary) |
goto failed; | goto failed; |
| |
self->library = Strdup(value); |
self->library = PAL_Strdup(value); |
| |
if (!self->library) | if (!self->library) |
goto failed; | goto failed; |
|
|
else if (strcmp(key, "HOSTING") == 0) | else if (strcmp(key, "HOSTING") == 0) |
{ | { |
if (hosting) | if (hosting) |
free(hosting); |
PAL_Free(hosting); |
| |
hosting = Strdup(value); |
hosting = PAL_Strdup(value); |
|
} |
|
else if (strcmp(key, "INSTANCELIFETIME") == 0) |
|
{ |
|
if (strcmp(value, "CONTEXT") == 0) |
|
{ |
|
self->instanceLifetimeContext = 1; |
|
} |
|
else |
|
{ |
|
goto failed; |
|
} |
|
} |
|
#if defined(CONFIG_ENABLE_PREEXEC) |
|
else if (strcmp(key, "PREEXEC") == 0) |
|
{ |
|
self->preexec = PAL_Strdup(value); |
} | } |
|
#endif /* defined(CONFIG_ENABLE_PREEXEC) */ |
else if (strcmp(key, "CLASS") == 0) | else if (strcmp(key, "CLASS") == 0) |
{ | { |
char* name; | char* name; |
|
|
if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0) | if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0) |
goto failed; | goto failed; |
| |
rc = (RegClass*)calloc(1, sizeof(RegClass)); |
rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass)); |
if (!rc) | if (!rc) |
goto failed; | goto failed; |
| |
|
|
(ListElem**)&self->classesTail, | (ListElem**)&self->classesTail, |
(ListElem*)rc); | (ListElem*)rc); |
| |
rc->name = Strdup(name); |
rc->name = PAL_Strdup(name); |
if (!rc->name) | if (!rc->name) |
goto failed; | goto failed; |
| |
if (refName1) | if (refName1) |
{ | { |
rc->refName1 = Strdup(refName1); |
rc->refName1 = PAL_Strdup(refName1); |
if (!rc->refName1) | if (!rc->refName1) |
goto failed; | goto failed; |
} | } |
| |
if (refName2) | if (refName2) |
{ | { |
rc->refName2 = Strdup(refName2); |
rc->refName2 = PAL_Strdup(refName2); |
if (!rc->refName2) | if (!rc->refName2) |
goto failed; | goto failed; |
} | } |
| |
if (hosting) | if (hosting) |
rc->hosting = Strdup(hosting); |
{ |
|
rc->hosting = PAL_Strdup(hosting); |
|
if(!rc->hosting) |
|
goto failed; |
} | } |
} | } |
|
else if (strcmp(key, "EXTRACLASS") == 0) |
|
{ |
|
char* name; |
|
char* refName1; |
|
char* refName2; |
|
RegClass* rc; |
|
|
|
if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0) |
|
goto failed; |
|
|
|
rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass)); |
|
if (!rc) |
|
goto failed; |
|
|
|
List_Append( |
|
(ListElem**)&self->extraClassesHead, |
|
(ListElem**)&self->extraClassesTail, |
|
(ListElem*)rc); |
|
|
|
rc->name = PAL_Strdup(name); |
|
if (!rc->name) |
|
goto failed; |
|
|
|
/* no need to use refName1, refName2 as the definition of these classes will be present as part of CLASSES list or EXTRACLASSES list */ |
| |
if (hosting) | if (hosting) |
free(hosting); |
{ |
|
rc->hosting = PAL_Strdup(hosting); |
|
if(!rc->hosting) |
|
goto failed; |
|
} |
|
} |
|
else if (strcmp(key, REG_INDICATION_CLASS) == 0) |
|
{ |
|
int r = ParseIndicationClass(&p, self, hosting, PROVREG_INDICATION); |
|
if (r == -1) |
|
goto failed; |
|
} |
|
} |
|
|
|
if (hosting) |
|
PAL_Free(hosting); |
|
|
|
/*If LIBRARY was not found (That should NOT happen), |
|
which means that this regfile is corrupted (The user might have modified it by hand). So go to failed*/ |
|
if(!foundLibrary) |
|
{ |
|
trace_RegFile_MissingLibraryTag(path); |
|
goto failed; |
|
} |
| |
fclose(is); | fclose(is); |
| |
|
|
return NULL; | return NULL; |
} | } |
| |
void RegFile_Delete(RegFile* self) |
static void _RegClassList_Delete(RegClass *regClassHead) |
{ | { |
RegClass* rc; | RegClass* rc; |
RegClass* next; | RegClass* next; |
| |
if (!self) |
for(rc = regClassHead; rc; rc = next) |
return; |
|
|
|
if (self->library) |
|
free(self->library); |
|
|
|
for (rc = self->classesHead; rc; rc = next) |
|
{ | { |
if (rc->name) | if (rc->name) |
free(rc->name); |
PAL_Free(rc->name); |
| |
if (rc->refName1) | if (rc->refName1) |
free(rc->refName1); |
PAL_Free(rc->refName1); |
| |
if (rc->refName2) | if (rc->refName2) |
free(rc->refName2); |
PAL_Free(rc->refName2); |
| |
if (rc->hosting) | if (rc->hosting) |
free(rc->hosting); |
PAL_Free(rc->hosting); |
| |
next = rc->next; | next = rc->next; |
free(rc); |
PAL_Free(rc); |
|
} |
} | } |
| |
free(self); |
void RegFile_Delete(RegFile* self) |
|
{ |
|
if (!self) |
|
return; |
|
|
|
if (self->library) |
|
PAL_Free(self->library); |
|
|
|
#if defined(CONFIG_ENABLE_PREEXEC) |
|
|
|
if (self->preexec) |
|
PAL_Free(self->preexec); |
|
|
|
#endif /* defined(CONFIG_ENABLE_PREEXEC) */ |
|
|
|
_RegClassList_Delete(self->classesHead); |
|
_RegClassList_Delete(self->extraClassesHead); |
|
|
|
PAL_Free(self); |
} | } |
| |
void RegFile_Print(RegFile* self, FILE* os) | void RegFile_Print(RegFile* self, FILE* os) |
{ | { |
RegClass* rc; | RegClass* rc; |
| |
fprintf(os, "LIBRARY=%s\n", self->library); |
Ftprintf(os, ZT("LIBRARY=%s\n"), scs(self->library)); |
|
|
|
#if defined(CONFIG_ENABLE_PREEXEC) |
|
|
|
Ftprintf(os, ZT("PREEXEC=%s\n"), scs(self->preexec)); |
|
|
|
#endif /* defined(CONFIG_ENABLE_PREEXEC) */ |
| |
for (rc = self->classesHead; rc; rc = rc->next) | for (rc = self->classesHead; rc; rc = rc->next) |
{ | { |
fprintf(os, "CLASS=%s", rc->name); |
Ftprintf(os, ZT("CLASS=%s"), scs(rc->name)); |
| |
if (rc->refName1 && rc->refName2) | if (rc->refName1 && rc->refName2) |
{ | { |
fprintf(os, "{"); |
Ftprintf(os, ZT("{")); |
fprintf(os, "%s", rc->refName1); |
Ftprintf(os, ZT("%s"), scs(rc->refName1)); |
fprintf(os, ","); |
Ftprintf(os, ZT(",")); |
fprintf(os, "%s", rc->refName2); |
Ftprintf(os, ZT("%s"), scs(rc->refName2)); |
fprintf(os, "}"); |
Ftprintf(os, ZT("}")); |
} | } |
| |
fprintf(os, "\n"); |
Ftprintf(os, ZT("\n")); |
} | } |
} | } |