/* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include "ipf.h" typedef struct variable { struct variable *v_next; char *v_name; char *v_value; } variable_t; static variable_t *vtop = NULL; static variable_t *find_var(char *); static char *expand_string(char *, int); static variable_t *find_var(name) char *name; { variable_t *v; for (v = vtop; v != NULL; v = v->v_next) if (!strcmp(name, v->v_name)) return (v); return (NULL); } char *get_variable(char *string, char **after, int line) { char c, *s, *t, *value; variable_t *v; s = string; if (*s == '{') { s++; for (t = s; *t != '\0'; t++) if (*t == '}') break; if (*t == '\0') { fprintf(stderr, "%d: { without }\n", line); return (NULL); } } else if (ISALPHA(*s)) { for (t = s + 1; *t != '\0'; t++) if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) break; } else { fprintf(stderr, "%d: variables cannot start with '%c'\n", line, *s); return (NULL); } if (after != NULL) *after = t; c = *t; *t = '\0'; v = find_var(s); *t = c; if (v == NULL) { fprintf(stderr, "%d: unknown variable '%s'\n", line, s); return (NULL); } s = strdup(v->v_value); value = expand_string(s, line); if (value != s) free(s); return (value); } static char *expand_string(char *oldstring, int line) { char c, *s, *p1, *p2, *p3, *newstring, *value; int len; p3 = NULL; newstring = oldstring; for (s = oldstring; *s != '\0'; s++) if (*s == '$') { *s = '\0'; s++; switch (*s) { case '$' : bcopy(s, s - 1, strlen(s)); break; default : c = *s; if (c == '\0') return (newstring); value = get_variable(s, &p3, line); if (value == NULL) return (NULL); p2 = expand_string(value, line); if (p2 == NULL) return (NULL); len = strlen(newstring) + strlen(p2); if (p3 != NULL) { if (c == '{' && *p3 == '}') p3++; len += strlen(p3); } p1 = malloc(len + 1); if (p1 == NULL) return (NULL); *(s - 1) = '\0'; strcpy(p1, newstring); strcat(p1, p2); if (p3 != NULL) strcat(p1, p3); s = p1 + len - strlen(p3) - 1; if (newstring != oldstring) free(newstring); newstring = p1; break; } } return (newstring); } void set_variable(char *name, char *value) { variable_t *v; int len; if (name == NULL || value == NULL || *name == '\0') return; v = find_var(name); if (v != NULL) { free(v->v_value); v->v_value = strdup(value); return; } len = strlen(value); if ((*value == '"' && value[len - 1] == '"') || (*value == '\'' && value[len - 1] == '\'')) { value[len - 1] = '\0'; value++; len -=2; } v = (variable_t *)malloc(sizeof(*v)); if (v == NULL) return; v->v_name = strdup(name); v->v_value = strdup(value); v->v_next = vtop; vtop = v; }