version 1.97, 2015/11/13 12:18:52 |
version 1.98, 2015/11/18 14:13:55 |
|
|
#define FORMAT_TIMESTRING 0x1 |
#define FORMAT_TIMESTRING 0x1 |
#define FORMAT_BASENAME 0x2 |
#define FORMAT_BASENAME 0x2 |
#define FORMAT_DIRNAME 0x4 |
#define FORMAT_DIRNAME 0x4 |
|
#define FORMAT_SUBSTITUTE 0x8 |
|
|
/* Entry in format tree. */ |
/* Entry in format tree. */ |
struct format_entry { |
struct format_entry { |
|
|
format_replace(struct format_tree *ft, const char *key, size_t keylen, |
format_replace(struct format_tree *ft, const char *key, size_t keylen, |
char **buf, size_t *len, size_t *off) |
char **buf, size_t *len, size_t *off) |
{ |
{ |
char *copy, *copy0, *endptr, *ptr, *saved, *trimmed, *value; |
char *copy, *copy0, *endptr, *ptr, *found, *new, *value; |
size_t valuelen; |
char *from = NULL, *to = NULL; |
|
size_t valuelen, newlen, fromlen, tolen, used; |
u_long limit = 0; |
u_long limit = 0; |
int modifiers = 0, brackets; |
int modifiers = 0, brackets; |
|
|
|
|
modifiers |= FORMAT_TIMESTRING; |
modifiers |= FORMAT_TIMESTRING; |
copy += 2; |
copy += 2; |
break; |
break; |
|
case 's': |
|
if (copy[1] != '/') |
|
break; |
|
from = copy + 2; |
|
for (copy = from; *copy != '\0' && *copy != '/'; copy++) |
|
/* nothing */; |
|
if (copy[0] != '/' || copy == from) { |
|
copy = copy0; |
|
break; |
|
} |
|
copy[0] = '\0'; |
|
to = copy + 1; |
|
for (copy = to; *copy != '\0' && *copy != '/'; copy++) |
|
/* nothing */; |
|
if (copy[0] != '/' || copy[1] != ':') { |
|
copy = copy0; |
|
break; |
|
} |
|
copy[0] = '\0'; |
|
|
|
modifiers |= FORMAT_SUBSTITUTE; |
|
copy += 2; |
|
break; |
} |
} |
|
|
/* |
/* |
|
|
*ptr = '\0'; |
*ptr = '\0'; |
|
|
value = ptr + 1; |
value = ptr + 1; |
saved = format_find(ft, copy + 1, modifiers); |
found = format_find(ft, copy + 1, modifiers); |
|
|
brackets = 0; |
brackets = 0; |
for (ptr = ptr + 1; *ptr != '\0'; ptr++) { |
for (ptr = ptr + 1; *ptr != '\0'; ptr++) { |
|
|
if (*ptr == '\0') |
if (*ptr == '\0') |
goto fail; |
goto fail; |
|
|
if (saved != NULL && *saved != '\0' && |
if (found != NULL && *found != '\0' && |
(saved[0] != '0' || saved[1] != '\0')) { |
(found[0] != '0' || found[1] != '\0')) { |
*ptr = '\0'; |
*ptr = '\0'; |
} else |
} else |
value = ptr + 1; |
value = ptr + 1; |
value = format_expand(ft, value); |
value = format_expand(ft, value); |
free(saved); |
free(found); |
saved = value; |
|
} else { |
} else { |
saved = value = format_find(ft, copy, modifiers); |
value = format_find(ft, copy, modifiers); |
if (value == NULL) |
if (value == NULL) |
saved = value = xstrdup(""); |
value = xstrdup(""); |
} |
} |
|
|
|
/* Perform substitution if any. */ |
|
if (modifiers & FORMAT_SUBSTITUTE) { |
|
fromlen = strlen(from); |
|
tolen = strlen(to); |
|
|
|
newlen = strlen(value) + 1; |
|
copy = new = xmalloc(newlen); |
|
for (ptr = value; *ptr != '\0'; /* nothing */) { |
|
if (strncmp(ptr, from, fromlen) != 0) { |
|
*new++ = *ptr++; |
|
continue; |
|
} |
|
used = new - copy; |
|
|
|
newlen += tolen; |
|
copy = xrealloc(copy, newlen); |
|
|
|
new = copy + used; |
|
memcpy(new, to, tolen); |
|
|
|
new += tolen; |
|
ptr += fromlen; |
|
} |
|
*new = '\0'; |
|
free(value); |
|
value = copy; |
|
} |
|
|
/* Truncate the value if needed. */ |
/* Truncate the value if needed. */ |
if (limit != 0) { |
if (limit != 0) { |
value = trimmed = utf8_trimcstr(value, limit); |
new = utf8_trimcstr(value, limit); |
free(saved); |
free(value); |
saved = trimmed; |
value = new; |
} |
} |
valuelen = strlen(value); |
|
|
|
/* Expand the buffer and copy in the value. */ |
/* Expand the buffer and copy in the value. */ |
|
valuelen = strlen(value); |
while (*len - *off < valuelen + 1) { |
while (*len - *off < valuelen + 1) { |
*buf = xreallocarray(*buf, 2, *len); |
*buf = xreallocarray(*buf, 2, *len); |
*len *= 2; |
*len *= 2; |
|
|
memcpy(*buf + *off, value, valuelen); |
memcpy(*buf + *off, value, valuelen); |
*off += valuelen; |
*off += valuelen; |
|
|
free(saved); |
free(value); |
free(copy0); |
free(copy0); |
return (0); |
return (0); |
|
|