summaryrefslogtreecommitdiff
path: root/glcdskin/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'glcdskin/parser.c')
-rw-r--r--glcdskin/parser.c185
1 files changed, 131 insertions, 54 deletions
diff --git a/glcdskin/parser.c b/glcdskin/parser.c
index b137a5f..31b3106 100644
--- a/glcdskin/parser.c
+++ b/glcdskin/parser.c
@@ -24,20 +24,20 @@ namespace GLCD
{
#define TAG_ERR_REMAIN(_context) do { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected tag %s within %s", \
- name.c_str(), _context); \
+ errorDetail = "Unexpected tag "+name+" within "+ _context; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} while (0)
#define TAG_ERR_CHILD(_context) do { \
- syslog(LOG_ERR, "ERROR: Text2Skin: No child tag %s expected within %s", \
- name.c_str(), _context); \
+ errorDetail = "No child tag "+name+" expected within "+ _context; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} while (0)
#define TAG_ERR_END(_context) do { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected closing tag for %s within %s", \
- name.c_str(), _context); \
+ errorDetail = "Unexpected closing tag for "+name+" within "+ _context; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} while (0)
@@ -49,8 +49,8 @@ namespace GLCD
#define ATTRIB_MAN_STRING(_attr,_target) \
ATTRIB_OPT_STRING(_attr,_target) \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
- _attr, name.c_str()); \
+ errorDetail = "Mandatory attribute "+ (std::string)_attr +" missing in tag "+ name; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
}
@@ -59,8 +59,8 @@ namespace GLCD
char *_e; const char *_t = attrs[_attr].c_str(); \
long _l = strtol(_t, &_e, 10); \
if (_e ==_t || *_e != '\0') { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Invalid numeric value \"%s\" in attribute %s", \
- _t, _attr); \
+ errorDetail = "Invalid numeric value \""+ (std::string)_t +"\" in attribute "+ (std::string)_attr; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} else \
_target = _l; \
@@ -69,8 +69,8 @@ namespace GLCD
#define ATTRIB_MAN_NUMBER(_attr,_target) \
ATTRIB_OPT_NUMBER(_attr,_target) \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
- _attr, name.c_str()); \
+ errorDetail = "Mandatory attribute "+ (std::string)_attr +" missing in tag "+name; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
}
@@ -81,8 +81,8 @@ namespace GLCD
else if (attrs[_attr] == "no") \
_target = false; \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Invalid boolean value \"%s\" in attribute %s", \
- attrs[_attr].c_str(), _attr); \
+ errorDetail = "Invalid boolean value \""+ attrs[_attr] +"\" in attribute "+ _attr; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} \
}
@@ -90,16 +90,16 @@ namespace GLCD
#define ATTRIB_MAN_BOOL(_attr,_target) \
ATTRIB_OPT_BOOL(_attr,_target) \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
- _attr, name.c_str()); \
+ errorDetail = "Mandatory attribute "+ (std::string)_attr +" missing in tag "+name; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
}
#define ATTRIB_OPT_FUNC(_attr,_func) \
if (attrs.find(_attr) != attrs.end()) { \
if (!_func(attrs[_attr])) { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected value %s for attribute %s", \
- attrs[_attr].c_str(), _attr); \
+ errorDetail = "Unexpected value \""+ attrs[_attr] +"\" for attribute "+ (std::string)_attr; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} \
}
@@ -107,16 +107,16 @@ namespace GLCD
#define ATTRIB_MAN_FUNC(_attr,_func) \
ATTRIB_OPT_FUNC(_attr,_func) \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
- _attr, name.c_str()); \
+ errorDetail = "Mandatory attribute "+ (std::string)_attr +" missing in tag "+name; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
}
#define ATTRIB_OPT_FUNC_PARAM(_attr,_func,_param) \
if (attrs.find(_attr) != attrs.end()) { \
if (!_func(attrs[_attr],_param)) { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected value %s for attribute %s", \
- attrs[_attr].c_str(), _attr); \
+ errorDetail = "Unexpected value "+ attrs[_attr] +" for attribute "+ (std::string)_attr; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
} \
}
@@ -124,8 +124,8 @@ namespace GLCD
#define ATTRIB_MAN_FUNC_PARAM(_attr,_func,_param) \
ATTRIB_OPT_FUNC_PARAM(_attr,_func,_param) \
else { \
- syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
- _attr, name.c_str()); \
+ errorDetail = "Mandatory attribute "+ (std::string)_attr +" missing in tag "+name; \
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str()); \
return false; \
}
@@ -133,31 +133,93 @@ static std::vector<std::string> context;
static cSkin * skin = NULL;
static cSkinFont * font = NULL;
static cSkinVariable * variable = NULL;
+static cSkinVariable * variable_default = NULL;
static cSkinDisplay * display = NULL;
static std::vector <cSkinObject *> parents;
static cSkinObject * object = NULL;
static uint32_t oindex = 0;
+static std::string errorDetail = "";
+static std::string condblock_cond = "";
+
+
+static bool CheckSkinVersion(const std::string & version) {
+ float currv;
+ char* ecptr = NULL;
+ const char* verscstr = version.c_str();
+ currv = strtof(verscstr, &ecptr);
+ if ( (*ecptr != '\0') || (ecptr == NULL) /*|| (ecptr != verscstr)*/ ||
+ ((int)(GLCDSKIN_SKIN_VERSION * 100.0) < (int)(currv * 100.0))
+ )
+ {
+ return false;
+ }
+ return true;
+}
+
+
bool StartElem(const std::string & name, std::map<std::string,std::string> & attrs)
{
//printf("start element: %s\n", name.c_str());
-
+// if (context.size() > 0) fprintf(stderr, "context: %s\n", context[context.size() - 1].c_str());
if (context.size() == 0)
{
if (name == "skin")
{
ATTRIB_MAN_STRING("version", skin->version);
ATTRIB_MAN_STRING("name", skin->title);
+ ATTRIB_OPT_FUNC("enable", skin->ParseEnable);
+
+ if (! CheckSkinVersion(skin->version) ) {
+ errorDetail = "skin version '"+ skin->version +"' not supported.";
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str());
+ return false;
+ }
}
else
TAG_ERR_REMAIN("document");
}
+ else if (name == "condblock")
+ {
+ int i = context.size() - 1;
+ while (i >= 0) {
+ if (context[i] == "condblock") {
+ errorDetail = "'condblock' must not be nested in another 'condblock'.";
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str());
+ return false;
+ }
+ i--;
+ }
+ ATTRIB_MAN_STRING("condition", condblock_cond);
+ }
else if (name == "variable")
{
variable = new cSkinVariable(skin);
ATTRIB_MAN_STRING("id", variable->mId);
ATTRIB_MAN_FUNC("value", variable->ParseValue);
- ATTRIB_OPT_FUNC("condition", variable->ParseCondition);
+ if (context[context.size() - 1] == "condblock") {
+ if (attrs.find("condition") != attrs.end()) {
+ errorDetail = "variable \""+variable->mId+"\" must not contain a condition when context = 'condblock'.";
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str());
+ return false;
+ } else {
+ if (! variable->ParseCondition(condblock_cond)) {
+ errorDetail = "Unexpected value \""+ attrs["condition"] +"\" for attribute "+ (std::string)"condition";
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: %s", errorDetail.c_str());
+ return false;
+ }
+ }
+ } else {
+ ATTRIB_OPT_FUNC("condition", variable->ParseCondition);
+ }
+ // if a 'default' value is set, create a second variable w/o condition: will be used if condition is not true
+ // as variables all have global scope (no matter where defined) and will always be sought from the start of the array,
+ // the default variable will be inserted _after_ the variable containing the condition.
+ if (attrs.find("default") != attrs.end()) {
+ variable_default = new cSkinVariable(skin);
+ ATTRIB_MAN_STRING("id", variable_default->mId);
+ ATTRIB_MAN_FUNC("default", variable_default->ParseValue);
+ }
}
else if (context[context.size() - 1] == "skin")
{
@@ -196,6 +258,7 @@ bool StartElem(const std::string & name, std::map<std::string,std::string> & att
ATTRIB_OPT_FUNC("width", object->ParseWidth);
ATTRIB_OPT_FUNC("height", object->ParseHeight);
ATTRIB_OPT_FUNC("condition", object->ParseCondition);
+ ATTRIB_OPT_STRING("action", object->mAction);
if (name == "image")
{
@@ -203,57 +266,57 @@ bool StartElem(const std::string & name, std::map<std::string,std::string> & att
ATTRIB_OPT_FUNC_PARAM("y", object->ParseIntParam, object->mPos1.y);
ATTRIB_OPT_FUNC_PARAM("x", object->ParseIntParam, object->mPos2.x);
ATTRIB_OPT_FUNC_PARAM("y", object->ParseIntParam, object->mPos2.y);
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
+ ATTRIB_OPT_FUNC_PARAM("bgcolor", object->ParseColor, object->mBackgroundColor);
ATTRIB_MAN_FUNC("path", object->mPath.Parse);
+ ATTRIB_OPT_FUNC("loop", object->ParseScrollLoopMode);
}
else if (name == "text"
|| name == "scrolltext")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
+ ATTRIB_OPT_FUNC_PARAM("bgcolor", object->ParseColor, object->mBackgroundColor);
ATTRIB_OPT_FUNC("align", object->ParseAlignment);
+ ATTRIB_OPT_FUNC("valign", object->ParseVerticalAlignment);
ATTRIB_OPT_FUNC("font", object->ParseFontFace);
ATTRIB_OPT_BOOL("multiline", object->mMultiline);
-#if 0
- if (name == "blink")
- {
- ATTRIB_OPT_NUMBER("delay", object->mDelay);
-
- if (object->mDelay == 0)
- object->mDelay = 1000;
- }
- else if (name == "marquee")
- {
- ATTRIB_OPT_NUMBER("delay", object->mDelay);
-
- if (object->mDelay == 0)
- object->mDelay = 500;
- }
-#endif
+ ATTRIB_OPT_FUNC("scrollmode", object->ParseScrollLoopMode);
+ ATTRIB_OPT_FUNC("scrollspeed", object->ParseScrollSpeed);
+ ATTRIB_OPT_FUNC("scrolltime", object->ParseScrollTime);
+ ATTRIB_OPT_STRING("alttext", object->mAltText);
+ ATTRIB_OPT_FUNC("altcondition", object->ParseAltCondition);
+ }
+ else if (name == "button")
+ {
+ ATTRIB_OPT_FUNC_PARAM("labelcolor", object->ParseColor, object->mColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mBackgroundColor);
+ ATTRIB_OPT_FUNC("font", object->ParseFontFace);
+ ATTRIB_OPT_NUMBER("radius", object->mRadius);
}
else if (name == "pixel")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
}
else if (name == "line")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
}
else if (name == "rectangle")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
ATTRIB_OPT_BOOL("filled", object->mFilled);
ATTRIB_OPT_NUMBER("radius", object->mRadius);
}
else if (name == "ellipse" || name == "slope")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
ATTRIB_OPT_BOOL("filled", object->mFilled);
ATTRIB_OPT_NUMBER("arc", object->mArc);
}
else if (name == "progress"
|| name == "scrollbar")
{
- ATTRIB_OPT_FUNC("color", object->ParseColor);
+ ATTRIB_OPT_FUNC_PARAM("color", object->ParseColor, object->mColor);
ATTRIB_OPT_NUMBER("direction", object->mDirection);
ATTRIB_OPT_FUNC("current", object->mCurrent.Parse);
ATTRIB_OPT_FUNC("total", object->mTotal.Parse);
@@ -284,7 +347,8 @@ bool CharData(const std::string & text)
//printf("context: %s\n", context[context.size() - 1].c_str());
if (context[context.size() - 1] == "text"
- || context[context.size() - 1] == "scrolltext")
+ || context[context.size() - 1] == "scrolltext"
+ || context[context.size() - 1] == "button")
{
if (!object->mText.Parse(text))
return false;
@@ -307,7 +371,13 @@ bool EndElem(const std::string & name)
else if (name == "variable")
{
skin->mVariables.push_back(variable);
+//fprintf(stderr, " variable '%s', value: %s\n", variable->mId.c_str(), ((std::string)variable->Value()).c_str());
variable = NULL;
+ if (variable_default != NULL) {
+ skin->mVariables.push_back(variable_default);
+//fprintf(stderr, " variable default '%s', value: %s\n", variable_default->mId.c_str(), ((std::string)variable_default->Value()).c_str());
+ variable_default = NULL;
+ }
}
else if (name == "display")
{
@@ -320,7 +390,7 @@ bool EndElem(const std::string & name)
{
if (object == NULL)
{
- printf("rotating parent to object\n");
+ //printf("rotating parent to object\n");
object = parents[parents.size() - 1];
parents.pop_back();
}
@@ -343,7 +413,7 @@ bool EndElem(const std::string & name)
#endif
if (parents.size() > 0)
{
- printf("pushing to parent\n");
+ //printf("pushing to parent\n");
cSkinObject *parent = parents[parents.size() - 1];
if (parent->mObjects == NULL)
parent->mObjects = new cSkinObjects();
@@ -360,7 +430,7 @@ bool EndElem(const std::string & name)
return true;
}
-cSkin * XmlParse(cSkinConfig & Config, const std::string & Name, const std::string & fileName)
+cSkin * XmlParse(cSkinConfig & Config, const std::string & Name, const std::string & fileName, std::string & errorString)
{
skin = new cSkin(Config, Name);
context.clear();
@@ -371,7 +441,13 @@ cSkin * XmlParse(cSkinConfig & Config, const std::string & Name, const std::stri
xml.SetCDataCB(CharData);
if (xml.Parse() != 0)
{
- syslog(LOG_ERR, "ERROR: Text2Skin: Parse error in %s, line %d", fileName.c_str(), xml.LineNr());
+ char buff[8];
+ snprintf(buff, 7, "%d", xml.LineNr());
+ syslog(LOG_ERR, "ERROR: graphlcd/skin: Parse error in %s, line %d", fileName.c_str(), xml.LineNr());
+ // shorter version outgoing errorString (eg. displaying errorString on the display)
+ errorString = "Parse error in skin "+Name+", line "+buff;
+ if (errorDetail != "")
+ errorString += ":\n"+errorDetail;
delete skin;
skin = NULL;
delete display;
@@ -383,6 +459,7 @@ cSkin * XmlParse(cSkinConfig & Config, const std::string & Name, const std::stri
cSkin * result = skin;
skin = NULL;
+ errorString = "";
return result;
}