Not technically related to INI parsing, but we use it with INI files. --- lib/libalpm/hook.c | 113 --------------------------------------------- src/common/ini.c | 113 +++++++++++++++++++++++++++++++++++++++++++++ src/common/ini.h | 3 ++ 3 files changed, 116 insertions(+), 113 deletions(-) diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index 6143ea0f..c385b5d5 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -17,7 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <ctype.h> #include <dirent.h> #include <errno.h> #include <limits.h> @@ -71,17 +70,6 @@ static void _alpm_trigger_free(struct _alpm_trigger_t *trigger) } } -static void _alpm_wordsplit_free(char **ws) -{ - if(ws) { - char **c; - for(c = ws; *c; c++) { - free(*c); - } - free(ws); - } -} - static void _alpm_hook_free(struct _alpm_hook_t *hook) { if(hook) { @@ -158,107 +146,6 @@ static int _alpm_hook_validate(alpm_handle_t *handle, return ret; } -static char **_alpm_wordsplit(char *str) -{ - char *c = str, *end; - char **out = NULL, **outsave; - size_t count = 0; - - if(str == NULL) { - errno = EINVAL; - return NULL; - } - - for(c = str; isspace(*c); c++); - while(*c) { - size_t wordlen = 0; - - /* extend our array */ - outsave = out; - if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { - out = outsave; - goto error; - } - - /* calculate word length and check for unbalanced quotes */ - for(end = c; *end && !isspace(*end); end++) { - if(*end == '\'' || *end == '"') { - char quote = *end; - while(*(++end) && *end != quote) { - if(*end == '\\' && *(end + 1) == quote) { - end++; - } - wordlen++; - } - if(*end != quote) { - errno = EINVAL; - goto error; - } - } else { - if(*end == '\\' && (end[1] == '\'' || end[1] == '"')) { - end++; /* skip the '\\' */ - } - wordlen++; - } - } - - if(wordlen == (size_t) (end - c)) { - /* no internal quotes or escapes, copy it the easy way */ - if((out[count++] = strndup(c, wordlen)) == NULL) { - goto error; - } - } else { - /* manually copy to remove quotes and escapes */ - char *dest = out[count++] = malloc(wordlen + 1); - if(dest == NULL) { goto error; } - while(c < end) { - if(*c == '\'' || *c == '"') { - char quote = *c; - /* we know there must be a matching end quote, - * no need to check for '\0' */ - for(c++; *c != quote; c++) { - if(*c == '\\' && *(c + 1) == quote) { - c++; - } - *(dest++) = *c; - } - c++; - } else { - if(*c == '\\' && (c[1] == '\'' || c[1] == '"')) { - c++; /* skip the '\\' */ - } - *(dest++) = *(c++); - } - } - *dest = '\0'; - } - - if(*end == '\0') { - break; - } else { - for(c = end + 1; isspace(*c); c++); - } - } - - outsave = out; - if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { - out = outsave; - goto error; - } - - out[count++] = NULL; - - return out; - -error: - /* can't use wordsplit_free here because NULL has not been appended */ - while(count) { - free(out[--count]); - } - free(out); - return NULL; -} - static int _alpm_hook_parse_cb(const char *file, int line, const char *section, char *key, char *value, void *data) { diff --git a/src/common/ini.c b/src/common/ini.c index 30f1fac8..9cdd5c47 100644 --- a/src/common/ini.c +++ b/src/common/ini.c @@ -17,6 +17,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <ctype.h> #include <errno.h> #include <limits.h> #include <stdlib.h> @@ -106,3 +107,115 @@ cleanup: free(section_name); return ret; } + +void _alpm_wordsplit_free(char **ws) +{ + if(ws) { + char **c; + for(c = ws; *c; c++) { + free(*c); + } + free(ws); + } +} + +char **_alpm_wordsplit(const char *str) +{ + const char *c = str, *end; + char **out = NULL, **outsave; + size_t count = 0; + + if(str == NULL) { + errno = EINVAL; + return NULL; + } + + for(c = str; isspace(*c); c++); + while(*c) { + size_t wordlen = 0; + + /* extend our array */ + outsave = out; + if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { + out = outsave; + goto error; + } + + /* calculate word length and check for unbalanced quotes */ + for(end = c; *end && !isspace(*end); end++) { + if(*end == '\'' || *end == '"') { + char quote = *end; + while(*(++end) && *end != quote) { + if(*end == '\\' && *(end + 1) == quote) { + end++; + } + wordlen++; + } + if(*end != quote) { + errno = EINVAL; + goto error; + } + } else { + if(*end == '\\' && (end[1] == '\'' || end[1] == '"')) { + end++; /* skip the '\\' */ + } + wordlen++; + } + } + + if(wordlen == (size_t) (end - c)) { + /* no internal quotes or escapes, copy it the easy way */ + if((out[count++] = strndup(c, wordlen)) == NULL) { + goto error; + } + } else { + /* manually copy to remove quotes and escapes */ + char *dest = out[count++] = malloc(wordlen + 1); + if(dest == NULL) { goto error; } + while(c < end) { + if(*c == '\'' || *c == '"') { + char quote = *c; + /* we know there must be a matching end quote, + * no need to check for '\0' */ + for(c++; *c != quote; c++) { + if(*c == '\\' && *(c + 1) == quote) { + c++; + } + *(dest++) = *c; + } + c++; + } else { + if(*c == '\\' && (c[1] == '\'' || c[1] == '"')) { + c++; /* skip the '\\' */ + } + *(dest++) = *(c++); + } + } + *dest = '\0'; + } + + if(*end == '\0') { + break; + } else { + for(c = end + 1; isspace(*c); c++); + } + } + + outsave = out; + if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { + out = outsave; + goto error; + } + + out[count++] = NULL; + + return out; + +error: + /* can't use wordsplit_free here because NULL has not been appended */ + while(count) { + free(out[--count]); + } + free(out); + return NULL; +} diff --git a/src/common/ini.h b/src/common/ini.h index 6d2b264a..b7c40f2c 100644 --- a/src/common/ini.h +++ b/src/common/ini.h @@ -25,4 +25,7 @@ typedef int (ini_parser_fn)(const char *file, int line, const char *section, int parse_ini(const char *file, ini_parser_fn cb, void *data); +void _alpm_wordsplit_free(char **ws); +char **_alpm_wordsplit(const char *str); + #endif /* PM_INI_H */ -- 2.21.0