From ce71d1643481424daf9c29979dde85b96b141107 Mon Sep 17 00:00:00 2001 From: kugel Date: Sun, 1 Nov 2009 23:35:14 +0000 Subject: [PATCH] Rework how feature skin tags work (%cc currently) when used conditionally (i.e. to detect a feature). If the feature is known to be unavailable at compile time or runtime detected, then let parsing skip over the true case. That enables parsing skins that properly put tags not available on a target within these tags. In the past the true case was parsed even if never could be true, which led to unexpected parsing failures. Parsing %cc<%St|time format|[..]|> is now possible on target where that setting doesn't exist (the %St parser wold fail). More of these tags are to be added, for example to indicate fm radio or recording capabilities. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23479 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_parser.c | 80 +++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index c05ebca45..7119024c6 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -1387,6 +1387,83 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) return skip; } + +/* + * Returns the number of bytes to skip the buf pointer to access the false + * branch in a _binary_ conditional + * + * That is: + * - before the '|' if we have a false branch, (%? -> %?<|false>) + * - or before the closing '>' if there's no false branch (%? -> %?<>) + * + * depending on the features of a target it's not called from check_feature_tag, + * hence the __attribute__ or it issues compiler warnings + * + **/ + +static int find_false_branch(const char *wps_bufptr) __attribute__((unused)); +static int find_false_branch(const char *wps_bufptr) +{ + const char *buf = wps_bufptr; + /* wps_bufptr is after the opening '<', hence level = 1*/ + int level = 1; + char ch; + do + { + ch = *buf; + if (ch == '%') + { /* filter out the characters we check later if they're printed + * as literals */ + ch = *(++buf); + if (ch == '<' || ch == '>' || ch == '|') + continue; + /* else: some tags/printed literals we skip over */ + } + else if (ch == '<') /* nested conditional */ + level++; + else if (ch == '>') + { /* closed our or a nested conditional, + * do NOT skip over the '>' so that wps_parse() sees it for closing + * if it is the closing one for our conditional */ + level--; + } + else if (ch == '|' && level == 1) + { /* we found our separator, point before and get out */ + break; + } + /* if level is 0, we don't have a false branch */ + } while (level > 0 && *(++buf)); + + return buf - wps_bufptr; +} + +/* + * returns the number of bytes to get the appropriate branch of a binary + * conditional + * + * That means: + * - if a feature is available, it returns 0 to not skip anything + * - if the feature is not available, skip to the false branch and don't + * parse the true branch at all + * + * */ +static int check_feature_tag(const char *wps_bufptr, const int type) +{ + (void)wps_bufptr; + switch (type) + { + case WPS_TOKEN_RTC_PRESENT: +#if CONFIG_RTC + return 0; +#else + return find_false_branch(wps_bufptr); +#endif + default: /* not a tag we care about, just don't skip */ + return 0; + } +} + + /* Parses the WPS. data is the pointer to the structure where the parsed WPS should be stored. It is initialised. @@ -1466,7 +1543,8 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) fail = PARSE_FAIL_COND_SYNTAX_ERROR; break; } - + wps_bufptr += check_feature_tag(wps_bufptr, + data->tokens[data->num_tokens-1].type); data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_START; lastcond[level] = data->num_tokens++; break; -- 2.11.4.GIT