var.c revision 145510
1/*	$NetBSD$	*/
2
3#include <ctype.h>
4
5#include "ipf.h"
6
7typedef	struct	variable	{
8	struct	variable	*v_next;
9	char	*v_name;
10	char	*v_value;
11} variable_t;
12
13static	variable_t	*vtop = NULL;
14
15static variable_t *find_var __P((char *));
16static char *expand_string __P((char *, int));
17
18
19static variable_t *find_var(name)
20char *name;
21{
22	variable_t *v;
23
24	for (v = vtop; v != NULL; v = v->v_next)
25		if (!strcmp(name, v->v_name))
26			return v;
27	return NULL;
28}
29
30
31char *get_variable(string, after, line)
32char *string, **after;
33int line;
34{
35	char c, *s, *t, *value;
36	variable_t *v;
37
38	s = string;
39
40	if (*s == '{') {
41		s++;
42		for (t = s; *t != '\0'; t++)
43			if (*t == '}')
44				break;
45		if (*t == '\0') {
46			fprintf(stderr, "%d: { without }\n", line);
47			return NULL;
48		}
49	} else if (ISALPHA(*s)) {
50		for (t = s + 1; *t != '\0'; t++)
51			if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
52				break;
53	} else {
54		fprintf(stderr, "%d: variables cannot start with '%c'\n",
55			line, *s);
56		return NULL;
57	}
58
59	if (after != NULL)
60		*after = t;
61	c = *t;
62	*t = '\0';
63	v = find_var(s);
64	*t = c;
65	if (v == NULL) {
66		fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
67		return NULL;
68	}
69
70	s = strdup(v->v_value);
71	value = expand_string(s, line);
72	if (value != s)
73		free(s);
74	return value;
75}
76
77
78static char *expand_string(oldstring, line)
79char *oldstring;
80int line;
81{
82	char c, *s, *p1, *p2, *p3, *newstring, *value;
83	int len;
84
85	p3 = NULL;
86	newstring = oldstring;
87
88	for (s = oldstring; *s != '\0'; s++)
89		if (*s == '$') {
90			*s = '\0';
91			s++;
92
93			switch (*s)
94			{
95			case '$' :
96				bcopy(s, s - 1, strlen(s));
97				break;
98			default :
99				c = *s;
100				if (c == '\0')
101					return newstring;
102
103				value = get_variable(s, &p3, line);
104				if (value == NULL)
105					return NULL;
106
107				p2 = expand_string(value, line);
108				if (p2 == NULL)
109					return NULL;
110
111				len = strlen(newstring) + strlen(p2);
112				if (p3 != NULL) {
113					if (c == '{' && *p3 == '}')
114						p3++;
115					len += strlen(p3);
116				}
117				p1 = malloc(len + 1);
118				if (p1 == NULL)
119					return NULL;
120
121				*(s - 1) = '\0';
122				strcpy(p1, newstring);
123				strcat(p1, p2);
124				if (p3 != NULL)
125					strcat(p1, p3);
126
127				s = p1 + len - strlen(p3) - 1;
128				if (newstring != oldstring)
129					free(newstring);
130				newstring = p1;
131				break;
132			}
133		}
134	return newstring;
135}
136
137
138void set_variable(name, value)
139char *name;
140char *value;
141{
142	variable_t *v;
143	int len;
144
145	if (name == NULL || value == NULL || *name == '\0')
146		return;
147
148	v = find_var(name);
149	if (v != NULL) {
150		free(v->v_value);
151		v->v_value = strdup(value);
152		return;
153	}
154
155	len = strlen(value);
156
157	if ((*value == '"' && value[len - 1] == '"') ||
158	    (*value == '\'' && value[len - 1] == '\'')) {
159		value[len - 1] = '\0';
160		value++;
161		len -=2;
162	}
163
164	v = (variable_t *)malloc(sizeof(*v));
165	if (v == NULL)
166		return;
167	v->v_name = strdup(name);
168	v->v_value = strdup(value);
169	v->v_next = vtop;
170	vtop = v;
171}
172