extract-word.c revision 27fc921b658adc5baa988c4c213888b016a60b18
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek This file is part of systemd.
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek Copyright 2010 Lennart Poettering
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek (at your option) any later version.
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmekint extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
613b411c947635136637f8cdd66b94512f761eabLennart Poettering bool backslash = false; /* whether we've just seen a backslash */
d8c9d3a468e61ee2a2b2c3454e662398b0885411Zbigniew Jędrzejewski-Szmek bool separator = false; /* whether we've just seen a separator */
613b411c947635136637f8cdd66b94512f761eabLennart Poettering /* Bail early if called after last value or with no input */
613b411c947635136637f8cdd66b94512f761eabLennart Poettering /* Parses the first word of a string, and returns it in
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * *ret. Removes all quotes in the process. When parsing fails
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * (because of an uneven number of quotes or similar), leaves
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * the pointer *p at the first invalid character. */
613b411c947635136637f8cdd66b94512f761eabLennart Poettering if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
613b411c947635136637f8cdd66b94512f761eabLennart Poettering for (;; (*p) ++, c = **p) {
613b411c947635136637f8cdd66b94512f761eabLennart Poettering if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
613b411c947635136637f8cdd66b94512f761eabLennart Poettering /* We found a non-blank character, so we will always
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * want to return a string (even if it is empty),
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * allocate it here. */
613b411c947635136637f8cdd66b94512f761eabLennart Poettering for (;; (*p) ++, c = **p) {
613b411c947635136637f8cdd66b94512f761eabLennart Poettering /* If we find an unquoted trailing backslash and we're in
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * Unbalanced quotes will only be allowed in EXTRACT_RELAX
613b411c947635136637f8cdd66b94512f761eabLennart Poettering * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
613b411c947635136637f8cdd66b94512f761eabLennart Poettering r = cunescape_one(*p, (size_t) -1, &c, &u);
613b411c947635136637f8cdd66b94512f761eabLennart Poettering (*p) += r - 1;
613b411c947635136637f8cdd66b94512f761eabLennart Poettering sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
6b46ea73e3b1d8a1e65f58ac04772821bd4a72fbLennart Poettering } else if (quote) { /* inside either single or double quotes */
6b46ea73e3b1d8a1e65f58ac04772821bd4a72fbLennart Poettering for (;; (*p) ++, c = **p) {
6b46ea73e3b1d8a1e65f58ac04772821bd4a72fbLennart Poettering } else if (c == quote) { /* found the end quote */
6b46ea73e3b1d8a1e65f58ac04772821bd4a72fbLennart Poettering } else if (c == '\\') {
613b411c947635136637f8cdd66b94512f761eabLennart Poettering for (;; (*p) ++, c = **p) {
goto finish;
goto finish_force_terminate;
quote = c;
backslash = true;
goto finish_force_next;
separator = true;
return -ENOMEM;
s[sz++] = c;
*p = NULL;
*p = NULL;
s[sz] = 0;
*ret = s;
s = NULL;
char **ret,
const char *separators,
const char *unit,
const char *filename,
unsigned line,
const char *rvalue) {
const char *save;
save = *p;
*p = save;
log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
if (r == -EINVAL)
return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
assert(p);
l = newa0(char*, n);
free(l[j]);
assert(v);