/* wydawca - automatic release submission daemon Copyright (C) 2007, 2008, 2009, 2010 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Wydawca is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with wydawca. If not, see . */ #include "wydawca.h" #include "sql.h" static const char * meta_expand (struct metadef *def, void *data) { if (!def->value) { if (def->expand) return def->expand (def, data); def->value = "INTERNAL ERROR: NONEXPANDABLE DATA"; } return def->value; } static const char * find_expansion_char (int c, struct metadef *def, void *data) { for (; def->kw; def++) if (def->kw[1] == 0 && def->kw[0] == c) return meta_expand (def, data); return NULL; } static const char * find_expansion_word (const char *kw, size_t len, struct metadef *def, void *data) { for (; def->kw; def++) if (strlen (def->kw) == len && memcmp (def->kw, kw, len) == 0) return meta_expand (def, data); return NULL; } char * meta_expand_string (const char *string, struct metadef *def, void *data, struct dictionary *dict, void *handle) { const char *p, *s; char *res; struct obstack stk; if (!string) return NULL; obstack_init (&stk); for (p = string; *p;) { char *e; size_t len = strcspn (p, "$"); obstack_grow (&stk, p, len); p += len; if (*p == '$') { switch (*++p) { case '$': obstack_grow (&stk, p, 1); p++; break; case '-': if (*++p) p++; break; case '{': e = strchr (p + 1, '}'); if (e && (s = find_expansion_word (p + 1, e - p - 1, def, data))) { if (dict) { char *newval; size_t len; /* FIXME: Return value? */ dictionary_quote_string (dict, handle, s, &newval, &len); obstack_grow (&stk, newval, len); free (newval); } else obstack_grow (&stk, s, strlen (s)); p = e + 1; } else { obstack_grow (&stk, p - 1, 2); p++; } break; default: if ((s = find_expansion_char (*p, def, data)) != NULL) len = strlen (s); else { s = p - 1; len = 1; } if (dict) { char *newval; size_t len; /* FIXME: Return value? */ dictionary_quote_string (dict, handle, s, &newval, &len); obstack_grow (&stk, newval, len); free (newval); } else obstack_grow (&stk, s, len); p++; } } else obstack_grow (&stk, p, 1); } obstack_1grow (&stk, 0); res = xstrdup (obstack_finish (&stk)); obstack_free (&stk, NULL); return res; } void meta_free (struct metadef *def) { for (; def->kw; def++) { if (def->storage) { free (def->storage); def->value = def->storage = NULL; } } }