version 1.154, 2018/04/18 14:35:37 |
version 1.155, 2018/05/22 08:49:12 |
|
|
return (copy); |
return (copy); |
} |
} |
|
|
/* Skip until comma. */ |
/* Skip until end. */ |
static char * |
static const char * |
format_skip(char *s) |
format_skip(const char *s, char end) |
{ |
{ |
int brackets = 0; |
int brackets = 0; |
|
|
for (; *s != '\0'; s++) { |
for (; *s != '\0'; s++) { |
if (*s == '{') |
if (*s == '#' && s[1] == '{') |
brackets++; |
brackets++; |
|
if (*s == '#' && strchr(",#{}", s[1]) != NULL) { |
|
s++; |
|
continue; |
|
} |
if (*s == '}') |
if (*s == '}') |
brackets--; |
brackets--; |
if (*s == ',' && brackets == 0) |
if (*s == end && brackets == 0) |
break; |
break; |
} |
} |
if (*s == '\0') |
if (*s == '\0') |
|
|
{ |
{ |
char *cp; |
char *cp; |
|
|
cp = format_skip(s); |
cp = (char *)format_skip(s, ','); |
if (cp == NULL) |
if (cp == NULL) |
return (-1); |
return (-1); |
*cp = '\0'; |
*cp = '\0'; |
|
|
size_t valuelen, newlen, fromlen, tolen, used; |
size_t valuelen, newlen, fromlen, tolen, used; |
long limit = 0; |
long limit = 0; |
int modifiers = 0, compare = 0, search = 0; |
int modifiers = 0, compare = 0, search = 0; |
|
int literal = 0; |
|
|
/* Make a copy of the key. */ |
/* Make a copy of the key. */ |
copy0 = copy = xmalloc(keylen + 1); |
copy0 = copy = xmalloc(keylen + 1); |
|
|
|
|
/* Is there a length limit or whatnot? */ |
/* Is there a length limit or whatnot? */ |
switch (copy[0]) { |
switch (copy[0]) { |
|
case 'l': |
|
if (copy[1] != ':') |
|
break; |
|
literal = 1; |
|
copy += 2; |
|
break; |
case 'm': |
case 'm': |
if (copy[1] != ':') |
if (copy[1] != ':') |
break; |
break; |
|
|
break; |
break; |
} |
} |
|
|
|
/* Is this a literal string? */ |
|
if (literal) { |
|
value = xstrdup(copy); |
|
goto done; |
|
} |
|
|
/* Is this a comparison or a conditional? */ |
/* Is this a comparison or a conditional? */ |
if (search) { |
if (search) { |
/* Search in pane. */ |
/* Search in pane. */ |
|
|
free(left); |
free(left); |
} else if (*copy == '?') { |
} else if (*copy == '?') { |
/* Conditional: check first and choose second or third. */ |
/* Conditional: check first and choose second or third. */ |
ptr = format_skip(copy); |
ptr = (char *)format_skip(copy, ','); |
if (ptr == NULL) |
if (ptr == NULL) |
goto fail; |
goto fail; |
*ptr = '\0'; |
*ptr = '\0'; |
|
|
} |
} |
|
|
/* Expand the buffer and copy in the value. */ |
/* Expand the buffer and copy in the value. */ |
|
done: |
valuelen = strlen(value); |
valuelen = strlen(value); |
while (*len - *off < valuelen + 1) { |
while (*len - *off < valuelen + 1) { |
*buf = xreallocarray(*buf, 2, *len); |
*buf = xreallocarray(*buf, 2, *len); |
|
|
fmt += n + 1; |
fmt += n + 1; |
continue; |
continue; |
case '{': |
case '{': |
brackets = 1; |
ptr = format_skip(fmt - 2, '}'); |
for (ptr = fmt; *ptr != '\0'; ptr++) { |
if (ptr == NULL) |
if (*ptr == '{') |
|
brackets++; |
|
if (*ptr == '}' && --brackets == 0) |
|
break; |
|
} |
|
if (*ptr != '}' || brackets != 0) |
|
break; |
break; |
n = ptr - fmt; |
n = ptr - fmt; |
|
|
|
|
break; |
break; |
fmt += n + 1; |
fmt += n + 1; |
continue; |
continue; |
|
case '}': |
case '#': |
case '#': |
|
case ',': |
while (len - off < 2) { |
while (len - off < 2) { |
buf = xreallocarray(buf, 2, len); |
buf = xreallocarray(buf, 2, len); |
len *= 2; |
len *= 2; |
} |
} |
buf[off++] = '#'; |
buf[off++] = ch; |
continue; |
continue; |
default: |
default: |
s = NULL; |
s = NULL; |