|
/***************************************************************************
|
|
begin : Mon Feb 08 2021
|
|
copyright : (C) 2021 by Martin Preuss
|
|
email : martin@libchipcard.de
|
|
|
|
***************************************************************************
|
|
* Please see toplevel file COPYING for license details *
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
|
|
#include "gwenbuild/parser/parser.h"
|
|
#include "gwenbuild/parser/p_project.h"
|
|
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/syncio.h>
|
|
#include <gwenhywfar/process.h>
|
|
#include <gwenhywfar/directory.h>
|
|
#include <gwenhywfar/text.h>
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
static int _parseSubdir(GWB_PROJECT *project, GWB_CONTEXT *currentContext, const char *sFolder, GWB_PARSER_PARSE_ELEMENT_FN fn);
|
|
static int _parseSetVar(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
|
|
static int _parseIfVarMatches(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn);
|
|
static int _parseIfNotVarMatches(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn);
|
|
static int _parseIfVarHasValue(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn);
|
|
static int _parseIfNotVarHasValue(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn);
|
|
static int _varHasValue(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
|
|
|
|
static int _parseWriteFile(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
|
|
static void _appendVarValue(GWEN_DB_NODE *db, const char *name, const char *newValue);
|
|
|
|
|
|
|
|
|
|
GWB_PROJECT *GWB_Parser_ReadBuildTree(GWENBUILD *gwbuild,
|
|
GWB_CONTEXT *currentContext,
|
|
const char *srcDir,
|
|
GWB_KEYVALUEPAIR_LIST *givenOptionList)
|
|
{
|
|
GWEN_XMLNODE *xmlNewFile;
|
|
GWEN_XMLNODE *xmlProject;
|
|
GWB_PROJECT *project;
|
|
int rv;
|
|
|
|
GWB_Context_SetInitialSourceDir(currentContext, srcDir);
|
|
GWB_Context_SetTopSourceDir(currentContext, srcDir);
|
|
GWB_Context_SetCurrentSourceDir(currentContext, srcDir);
|
|
|
|
xmlNewFile=GWB_Parser_ReadBuildFile(gwbuild, currentContext, GWB_PARSER_FILENAME);
|
|
if (xmlNewFile==NULL) {
|
|
DBG_ERROR(NULL, "No valid node found in build file of folder \"%s\"", srcDir);
|
|
return NULL;
|
|
}
|
|
|
|
xmlProject=GWEN_XMLNode_FindFirstTag(xmlNewFile, "project", NULL, NULL);
|
|
if (xmlProject==NULL) {
|
|
DBG_ERROR(NULL, "No project node found in build file of folder \"%s\"", srcDir);
|
|
GWEN_XMLNode_free(xmlNewFile);
|
|
return NULL;
|
|
}
|
|
|
|
project=GWB_Project_new(gwbuild, currentContext);
|
|
if (givenOptionList)
|
|
GWB_Project_SetGivenOptionList(project, givenOptionList);
|
|
|
|
rv=GWB_ParseProject(project, currentContext, xmlProject);
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Error parsing build tree in folder \"%s\"", srcDir);
|
|
GWB_Project_free(project);
|
|
GWEN_XMLNode_free(xmlNewFile);
|
|
return NULL;
|
|
}
|
|
|
|
GWEN_XMLNode_free(xmlNewFile);
|
|
return project;
|
|
}
|
|
|
|
|
|
|
|
GWB_CONTEXT *GWB_Parser_CopyContextForSubdir(const GWB_CONTEXT *sourceContext, const char *folder)
|
|
{
|
|
GWB_CONTEXT *newContext;
|
|
GWEN_DB_NODE *db;
|
|
|
|
newContext=GWB_Context_dup(sourceContext);
|
|
|
|
GWB_Context_AddCurrentRelativeDir(newContext, folder);
|
|
|
|
GWB_Context_InsertTopBuildDir(newContext, "..");
|
|
GWB_Context_InsertTopSourceDir(newContext, "..");
|
|
|
|
GWB_Context_AddCurrentBuildDir(newContext, folder);
|
|
|
|
GWB_Context_InsertCurrentSourceDir(newContext, "..");
|
|
GWB_Context_AddCurrentSourceDir(newContext, folder);
|
|
|
|
GWB_Context_ClearSourceFileList2(newContext);
|
|
GWB_Context_ClearIncludeList(newContext);
|
|
GWB_Context_ClearDefineList(newContext);
|
|
|
|
db=GWB_Context_GetVars(newContext);
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "topbuilddir", GWB_Context_GetTopBuildDir(newContext));
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "topsrcdir", GWB_Context_GetTopSourceDir(newContext));
|
|
//GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "builddir", GWB_Context_GetCurrentBuildDir(newContext));
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "builddir", ".");
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "srcdir", GWB_Context_GetCurrentSourceDir(newContext));
|
|
|
|
GWEN_DB_DeleteGroup(db, "local");
|
|
|
|
return newContext;
|
|
}
|
|
|
|
|
|
|
|
GWB_CONTEXT *GWB_Parser_CopyContextForTarget(const GWB_CONTEXT *sourceContext)
|
|
{
|
|
GWB_CONTEXT *newContext;
|
|
|
|
newContext=GWB_Context_dup(sourceContext);
|
|
|
|
GWB_Context_ClearSourceFileList2(newContext);
|
|
GWB_Context_ClearIncludeList(newContext);
|
|
GWB_Context_ClearDefineList(newContext);
|
|
|
|
return newContext;
|
|
}
|
|
|
|
|
|
|
|
GWEN_XMLNODE *GWB_Parser_ReadBuildFile(GWENBUILD *gwbuild, const GWB_CONTEXT *currentContext, const char *fileName)
|
|
{
|
|
GWEN_BUFFER *fileNameBuf;
|
|
const char *s;
|
|
int rv;
|
|
GWEN_XMLNODE *xmlDocNode;
|
|
GWEN_XMLNODE *xmlGwbuildNode;
|
|
|
|
fileNameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
|
s=GWB_Context_GetCurrentSourceDir(currentContext);
|
|
if (s && *s) {
|
|
GWEN_Buffer_AppendString(fileNameBuf, s);
|
|
GWEN_Buffer_AppendString(fileNameBuf, GWEN_DIR_SEPARATOR_S);
|
|
}
|
|
GWEN_Buffer_AppendString(fileNameBuf, fileName);
|
|
|
|
xmlDocNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "root");
|
|
|
|
DBG_DEBUG(NULL, "Reading file %s", GWEN_Buffer_GetStart(fileNameBuf));
|
|
rv=GWEN_XML_ReadFile(xmlDocNode, GWEN_Buffer_GetStart(fileNameBuf), GWEN_XML_FLAGS_DEFAULT);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here %d)", rv);
|
|
GWEN_Buffer_free(fileNameBuf);
|
|
return NULL;
|
|
}
|
|
|
|
xmlGwbuildNode=GWEN_XMLNode_FindFirstTag(xmlDocNode, "gwbuild", NULL, NULL);
|
|
if (xmlGwbuildNode==NULL) {
|
|
DBG_ERROR(NULL, "File \"%s\" does not contain an \"gwbuild\" element", GWEN_Buffer_GetStart(fileNameBuf));
|
|
GWEN_XMLNode_free(xmlDocNode);
|
|
GWEN_Buffer_free(fileNameBuf);
|
|
return NULL;
|
|
}
|
|
|
|
if (1) {
|
|
GWEN_BUFFER *buildFilenameBuffer;
|
|
const char *buildDir;
|
|
const char *initialSourceDir;
|
|
|
|
initialSourceDir=GWB_Context_GetInitialSourceDir(currentContext);
|
|
buildDir=GWB_Context_GetCurrentBuildDir(currentContext);
|
|
buildFilenameBuffer=GWEN_Buffer_new(0, 256, 0, 1);
|
|
GWEN_Buffer_AppendString(buildFilenameBuffer, initialSourceDir);
|
|
if (buildDir) {
|
|
GWEN_Buffer_AppendString(buildFilenameBuffer, GWEN_DIR_SEPARATOR_S);
|
|
GWEN_Buffer_AppendString(buildFilenameBuffer, buildDir);
|
|
}
|
|
GWEN_Buffer_AppendString(buildFilenameBuffer, GWEN_DIR_SEPARATOR_S);
|
|
GWEN_Buffer_AppendString(buildFilenameBuffer, fileName);
|
|
GWBUILD_AddBuildFilename(gwbuild, GWEN_Buffer_GetStart(buildFilenameBuffer));
|
|
GWEN_Buffer_free(buildFilenameBuffer);
|
|
}
|
|
|
|
GWEN_XMLNode_UnlinkChild(xmlDocNode, xmlGwbuildNode);
|
|
GWEN_XMLNode_free(xmlDocNode);
|
|
GWEN_Buffer_free(fileNameBuf);
|
|
|
|
return xmlGwbuildNode;
|
|
}
|
|
|
|
|
|
|
|
GWEN_STRINGLIST *GWB_Parser_ReadXmlDataIntoStringList(GWEN_DB_NODE *db, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
GWEN_BUFFER *buf;
|
|
|
|
buf=GWB_Parser_ReadXmlDataIntoBufferAndExpand(db, xmlNode);
|
|
if (buf) {
|
|
GWEN_STRINGLIST *sl;
|
|
|
|
sl=GWEN_StringList_fromString(GWEN_Buffer_GetStart(buf), " ", 1);
|
|
if (sl==NULL) {
|
|
DBG_ERROR(NULL, "Could not generate string list from data [%s]", GWEN_Buffer_GetStart(buf));
|
|
GWEN_Buffer_free(buf);
|
|
return NULL;
|
|
}
|
|
GWEN_Buffer_free(buf);
|
|
|
|
return sl;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
GWEN_BUFFER *GWB_Parser_ReadXmlDataIntoBufferAndExpand(GWEN_DB_NODE *db, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
GWEN_XMLNODE *xmlData;
|
|
|
|
xmlData=GWEN_XMLNode_GetFirstData(xmlNode);
|
|
if (xmlData) {
|
|
const char *s;
|
|
|
|
s=GWEN_XMLNode_GetData(xmlData);
|
|
if (s && *s) {
|
|
int rv;
|
|
GWEN_BUFFER *buf;
|
|
|
|
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
|
rv=GWEN_DB_ReplaceVars(db, s, buf);
|
|
if(rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
GWEN_Buffer_free(buf);
|
|
return NULL;
|
|
}
|
|
if (GWEN_Buffer_GetUsedBytes(buf)==0) {
|
|
GWEN_Buffer_free(buf);
|
|
return NULL;
|
|
}
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
int GWB_Parser_ParseSubdirs(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
GWEN_STRINGLIST *sl;
|
|
|
|
sl=GWB_Parser_ReadXmlDataIntoStringList(GWB_Context_GetVars(currentContext), xmlNode);
|
|
if (sl) {
|
|
GWEN_STRINGLISTENTRY *se;
|
|
|
|
se=GWEN_StringList_FirstEntry(sl);
|
|
while(se) {
|
|
const char *sFolder;
|
|
|
|
sFolder=GWEN_StringListEntry_Data(se);
|
|
if (sFolder && *sFolder) {
|
|
int rv;
|
|
|
|
rv=GWEN_Directory_GetPath(sFolder, 0);
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Could not create folder \"%s\" in build tree", sFolder);
|
|
return rv;
|
|
}
|
|
if (chdir(sFolder)==-1) {
|
|
DBG_ERROR(NULL, "Could not enter folder \"%s\" in build tree (%s)",
|
|
sFolder, strerror(errno));
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
rv=_parseSubdir(project, currentContext, sFolder, fn);
|
|
chdir("..");
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
se=GWEN_StringListEntry_Next(se);
|
|
}
|
|
GWEN_StringList_free(sl);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseSubdir(GWB_PROJECT *project, GWB_CONTEXT *currentContext, const char *sFolder, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
|
|
GWB_CONTEXT *newContext;
|
|
GWEN_XMLNODE *xmlNewFile;
|
|
int rv;
|
|
|
|
newContext=GWB_Parser_CopyContextForSubdir(currentContext, sFolder);
|
|
|
|
fprintf(stdout, "Entering folder \"%s\"\n", sFolder);
|
|
xmlNewFile=GWB_Parser_ReadBuildFile(GWB_Project_GetGwbuild(project), newContext, GWB_PARSER_FILENAME);
|
|
if (xmlNewFile==NULL) {
|
|
DBG_ERROR(NULL, "No valid node found in build file of subdir \"%s\"", sFolder);
|
|
GWB_Context_free(newContext);
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
|
|
rv=fn(project, newContext, xmlNewFile);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
GWEN_XMLNode_free(xmlNewFile);
|
|
GWB_Context_free(newContext);
|
|
return rv;
|
|
}
|
|
GWEN_XMLNode_free(xmlNewFile);
|
|
|
|
GWB_Context_Tree2_AddChild(currentContext, newContext);
|
|
fprintf(stdout, "Leaving folder \"%s\"\n", sFolder);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseSetVar(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
const char *sName;
|
|
const char *sMode;
|
|
GWEN_BUFFER *buf;
|
|
GWEN_DB_NODE *db;
|
|
|
|
db=GWB_Context_GetVars(currentContext);
|
|
|
|
sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
|
|
if (!(sName && *sName)) {
|
|
DBG_ERROR(NULL, "No name for <setVar>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
if (GWEN_XMLNode_GetProperty(xmlNode, "value", NULL)) {
|
|
DBG_WARN(NULL,
|
|
"%s: Please dont use property \"value\", just store the value between <setVar> and </setVar>",
|
|
sName);
|
|
}
|
|
|
|
sMode=GWEN_XMLNode_GetProperty(xmlNode, "mode", "replace");
|
|
|
|
buf=GWB_Parser_ReadXmlDataIntoBufferAndExpand(GWB_Context_GetVars(currentContext), xmlNode);
|
|
if (buf && GWEN_Buffer_GetUsedBytes(buf)) {
|
|
if (strcasecmp(sMode, "replace")==0)
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, GWEN_Buffer_GetStart(buf));
|
|
else if (strcasecmp(sMode, "add")==0)
|
|
GWEN_DB_SetCharValue(db, 0, sName, GWEN_Buffer_GetStart(buf));
|
|
else if (strcasecmp(sMode, "append")==0)
|
|
_appendVarValue(db, sName, GWEN_Buffer_GetStart(buf));
|
|
GWEN_Buffer_free(buf);
|
|
}
|
|
else {
|
|
if (strcasecmp(sMode, "replace")==0) {
|
|
GWEN_DB_DeleteVar(db, sName);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseIfVarMatches(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
const char *sName;
|
|
const char *sPattern;
|
|
const char *sValueInDb;
|
|
GWEN_DB_NODE *db;
|
|
GWEN_XMLNODE *xmlThen;
|
|
GWEN_XMLNODE *xmlElse;
|
|
int rv;
|
|
|
|
xmlThen=GWEN_XMLNode_FindFirstTag(xmlNode, "then", NULL, NULL);
|
|
xmlElse=GWEN_XMLNode_FindFirstTag(xmlNode, "else", NULL, NULL);
|
|
|
|
db=GWB_Context_GetVars(currentContext);
|
|
|
|
sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
|
|
if (!(sName && *sName)) {
|
|
DBG_ERROR(NULL, "No name for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
sPattern=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
|
|
if (!(sPattern && *sPattern)) {
|
|
DBG_ERROR(NULL, "No value for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
sValueInDb=GWEN_DB_GetCharValue(db, sName, 0, NULL);
|
|
if (!(sValueInDb && *sValueInDb)) {
|
|
DBG_ERROR(NULL, "No value for \"%s\" in db for <ifVarMatches>", sName);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
if (-1!=GWEN_Text_ComparePattern(sValueInDb, sPattern, 0)) {
|
|
rv=fn(project, currentContext, xmlThen?xmlThen:xmlNode);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
if (xmlElse) {
|
|
rv=fn(project, currentContext, xmlElse);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseIfNotVarMatches(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
const char *sName;
|
|
const char *sPattern;
|
|
const char *sValueInDb;
|
|
GWEN_DB_NODE *db;
|
|
GWEN_XMLNODE *xmlThen;
|
|
GWEN_XMLNODE *xmlElse;
|
|
int rv;
|
|
|
|
xmlThen=GWEN_XMLNode_FindFirstTag(xmlNode, "then", NULL, NULL);
|
|
xmlElse=GWEN_XMLNode_FindFirstTag(xmlNode, "else", NULL, NULL);
|
|
|
|
db=GWB_Context_GetVars(currentContext);
|
|
|
|
sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
|
|
if (!(sName && *sName)) {
|
|
DBG_ERROR(NULL, "No name for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
sPattern=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
|
|
if (!(sPattern && *sPattern)) {
|
|
DBG_ERROR(NULL, "No value for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
sValueInDb=GWEN_DB_GetCharValue(db, sName, 0, NULL);
|
|
if (!(sValueInDb && *sValueInDb)) {
|
|
DBG_ERROR(NULL, "No value for \"%s\" in db for <ifVarMatches>", sName);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
if (-1==GWEN_Text_ComparePattern(sValueInDb, sPattern, 0)) {
|
|
rv=fn(project, currentContext, xmlThen?xmlThen:xmlNode);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
if (xmlElse) {
|
|
rv=fn(project, currentContext, xmlElse);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseIfVarHasValue(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
int rv;
|
|
GWEN_XMLNODE *xmlThen;
|
|
GWEN_XMLNODE *xmlElse;
|
|
|
|
xmlThen=GWEN_XMLNode_FindFirstTag(xmlNode, "then", NULL, NULL);
|
|
xmlElse=GWEN_XMLNode_FindFirstTag(xmlNode, "else", NULL, NULL);
|
|
rv=_varHasValue(currentContext, xmlNode);
|
|
if (rv<0)
|
|
return rv;
|
|
if (rv) {
|
|
return fn(project, currentContext, xmlThen?xmlThen:xmlNode);
|
|
}
|
|
else {
|
|
if (xmlElse)
|
|
return fn(project, currentContext, xmlElse);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseIfNotVarHasValue(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
int rv;
|
|
GWEN_XMLNODE *xmlThen;
|
|
GWEN_XMLNODE *xmlElse;
|
|
|
|
xmlThen=GWEN_XMLNode_FindFirstTag(xmlNode, "then", NULL, NULL);
|
|
xmlElse=GWEN_XMLNode_FindFirstTag(xmlNode, "else", NULL, NULL);
|
|
rv=_varHasValue(currentContext, xmlNode);
|
|
if (rv<0)
|
|
return rv;
|
|
if (rv==0) {
|
|
return fn(project, currentContext, xmlThen?xmlThen:xmlNode);
|
|
}
|
|
else {
|
|
if (xmlElse)
|
|
return fn(project, currentContext, xmlElse);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _varHasValue(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
const char *sName;
|
|
const char *sPattern;
|
|
GWEN_DB_NODE *db;
|
|
int i;
|
|
|
|
db=GWB_Context_GetVars(currentContext);
|
|
|
|
sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
|
|
if (!(sName && *sName)) {
|
|
DBG_ERROR(NULL, "No name for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
sPattern=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
|
|
if (!(sPattern && *sPattern)) {
|
|
DBG_ERROR(NULL, "No value for <ifVarMatches>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
for (i=0; i<100; i++) {
|
|
const char *sValueInDb;
|
|
|
|
sValueInDb=GWEN_DB_GetCharValue(db, sName, i, NULL);
|
|
if (!sValueInDb)
|
|
break;
|
|
if (-1!=GWEN_Text_ComparePattern(sValueInDb, sPattern, 0))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _parseWriteFile(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
const char *fileName;
|
|
const char *currentSrcDir;
|
|
GWEN_BUFFER *fileNameBuffer;
|
|
GWEN_BUFFER *fileBufferIn;
|
|
GWEN_BUFFER *fileBufferOut;
|
|
GWB_FILE *file;
|
|
int rv;
|
|
|
|
fileName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
|
|
if (!(fileName && *fileName)) {
|
|
DBG_ERROR(NULL, "No name for <writeFile>");
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
currentSrcDir=GWB_Context_GetCurrentSourceDir(currentContext);
|
|
|
|
fileNameBuffer=GWEN_Buffer_new(0, 256, 0, 1);
|
|
if (currentSrcDir && *currentSrcDir) {
|
|
GWEN_Buffer_AppendString(fileNameBuffer, currentSrcDir);
|
|
GWEN_Buffer_AppendString(fileNameBuffer, GWEN_DIR_SEPARATOR_S);
|
|
}
|
|
GWEN_Buffer_AppendString(fileNameBuffer, fileName);
|
|
GWEN_Buffer_AppendString(fileNameBuffer, ".in");
|
|
|
|
fileBufferIn=GWEN_Buffer_new(0, 256, 0, 1);
|
|
|
|
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fileNameBuffer), fileBufferIn);
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Could not read \"%s\" (%d)", GWEN_Buffer_GetStart(fileNameBuffer), rv);
|
|
GWEN_Buffer_free(fileBufferIn);
|
|
GWEN_Buffer_free(fileNameBuffer);
|
|
return rv;
|
|
}
|
|
|
|
fileBufferOut=GWEN_Buffer_new(0, 256, 0, 1);
|
|
rv=GWB_Parser_ReplaceVarsBetweenAtSigns(GWEN_Buffer_GetStart(fileBufferIn),
|
|
fileBufferOut,
|
|
GWB_Context_GetVars(currentContext));
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Error translating content of file \"%s\" (%d)", GWEN_Buffer_GetStart(fileNameBuffer), rv);
|
|
GWEN_Buffer_free(fileBufferOut);
|
|
GWEN_Buffer_free(fileBufferIn);
|
|
GWEN_Buffer_free(fileNameBuffer);
|
|
return rv;
|
|
}
|
|
|
|
unlink(fileName);
|
|
rv=GWEN_SyncIo_Helper_WriteFile(fileName,
|
|
(const uint8_t*)GWEN_Buffer_GetStart(fileBufferOut),
|
|
GWEN_Buffer_GetUsedBytes(fileBufferOut));
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Could not write \"%sh\" (%d)", fileName, rv);
|
|
GWEN_Buffer_free(fileBufferOut);
|
|
GWEN_Buffer_free(fileBufferIn);
|
|
GWEN_Buffer_free(fileNameBuffer);
|
|
return rv;
|
|
}
|
|
|
|
/* add output file */
|
|
file=GWB_File_List2_GetOrCreateFile(GWB_Project_GetFileList(project),
|
|
GWB_Context_GetCurrentRelativeDir(currentContext),
|
|
fileName);
|
|
GWB_File_AddFlags(file, GWB_FILE_FLAGS_GENERATED);
|
|
|
|
/* add input file */
|
|
GWEN_Buffer_Reset(fileNameBuffer);
|
|
GWEN_Buffer_AppendString(fileNameBuffer, fileName);
|
|
GWEN_Buffer_AppendString(fileNameBuffer, ".in");
|
|
GWB_File_List2_GetOrCreateFile(GWB_Project_GetFileList(project),
|
|
GWB_Context_GetCurrentRelativeDir(currentContext),
|
|
GWEN_Buffer_GetStart(fileNameBuffer));
|
|
|
|
GWEN_Buffer_free(fileBufferOut);
|
|
GWEN_Buffer_free(fileBufferIn);
|
|
GWEN_Buffer_free(fileNameBuffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _appendVarValue(GWEN_DB_NODE *db, const char *name, const char *newValue)
|
|
{
|
|
const char *s;
|
|
|
|
s=GWEN_DB_GetCharValue(db, name, 0, NULL);
|
|
if (s && *s) {
|
|
GWEN_BUFFER *buf;
|
|
|
|
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
|
GWEN_Buffer_AppendString(buf, s);
|
|
GWEN_Buffer_AppendString(buf, " ");
|
|
GWEN_Buffer_AppendString(buf, newValue);
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, name, GWEN_Buffer_GetStart(buf));
|
|
GWEN_Buffer_free(buf);
|
|
}
|
|
else
|
|
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, name, newValue);
|
|
}
|
|
|
|
|
|
|
|
void GWB_Parser_SetItemValue(GWEN_DB_NODE *db, const char *sId, const char *suffix, const char *value)
|
|
{
|
|
GWEN_BUFFER *varNameBuffer;
|
|
|
|
varNameBuffer=GWEN_Buffer_new(0, 64, 0, 1);
|
|
GWEN_Buffer_AppendString(varNameBuffer, sId);
|
|
GWEN_Buffer_AppendString(varNameBuffer, suffix);
|
|
GWEN_DB_SetCharValue(db,
|
|
GWEN_DB_FLAGS_OVERWRITE_VARS,
|
|
GWEN_Buffer_GetStart(varNameBuffer),
|
|
value);
|
|
GWEN_Buffer_free(varNameBuffer);
|
|
}
|
|
|
|
|
|
|
|
|
|
int GWB_Parser_ReplaceVarsBetweenAtSigns(const char *s, GWEN_BUFFER *dbuf, GWEN_DB_NODE *db)
|
|
{
|
|
const char *p;
|
|
|
|
#if 0
|
|
DBG_ERROR(NULL, "Using vars:");
|
|
GWEN_DB_Dump(db, 2);
|
|
#endif
|
|
|
|
p=s;
|
|
while (*p) {
|
|
if (*p=='@') {
|
|
p++;
|
|
if (*p=='@')
|
|
GWEN_Buffer_AppendByte(dbuf, '@');
|
|
else {
|
|
const char *pStart;
|
|
|
|
pStart=p;
|
|
while (*p && *p!='@')
|
|
p++;
|
|
if (*p!='@') {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Unterminated variable name in code");
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
else {
|
|
int len;
|
|
char *rawName;
|
|
const char *value;
|
|
|
|
len=p-pStart;
|
|
if (len<1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Empty variable name in code");
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
rawName=(char *) malloc(len+1);
|
|
assert(rawName);
|
|
memmove(rawName, pStart, len);
|
|
rawName[len]=0;
|
|
|
|
/*DBG_ERROR(NULL, "Setting data from variable \"%s\"", rawName);*/
|
|
value=GWEN_DB_GetCharValue(db, rawName, 0, NULL);
|
|
if (value)
|
|
GWEN_Buffer_AppendString(dbuf, value);
|
|
else {
|
|
DBG_WARN(NULL, "Warning: Empty value for DB var \"%s\"", rawName);
|
|
}
|
|
free(rawName);
|
|
}
|
|
}
|
|
p++;
|
|
}
|
|
else {
|
|
GWEN_Buffer_AppendByte(dbuf, *p);
|
|
p++;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWB_Parser_ParseWellKnownElements(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn)
|
|
{
|
|
const char *name;
|
|
|
|
name=GWEN_XMLNode_GetData(n);
|
|
if (name && *name) {
|
|
int rv;
|
|
|
|
DBG_DEBUG(NULL, "Handling element \"%s\"", name);
|
|
|
|
if (strcasecmp(name, "writeFile")==0)
|
|
rv=_parseWriteFile(project, currentContext, n);
|
|
else if (strcasecmp(name, "setVar")==0)
|
|
rv=_parseSetVar(currentContext, n);
|
|
else if (strcasecmp(name, "ifVarMatches")==0)
|
|
rv=_parseIfVarMatches(project, currentContext, n, fn);
|
|
else if (strcasecmp(name, "ifNotVarMatches")==0)
|
|
rv=_parseIfNotVarMatches(project, currentContext, n, fn);
|
|
else if (strcasecmp(name, "ifVarHasValue")==0)
|
|
rv=_parseIfVarHasValue(project, currentContext, n, fn);
|
|
else if (strcasecmp(name, "ifNotVarHasValue")==0)
|
|
rv=_parseIfNotVarHasValue(project, currentContext, n, fn);
|
|
else {
|
|
DBG_DEBUG(NULL, "Element not handled here, ignoring");
|
|
rv=1;
|
|
}
|
|
if (rv<0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|