2 macros.c - a simple macro expander
4 Copyright (c) 2010, 2014 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include <vppinfra/macros.h>
21 static inline int macro_isalnum (i8 c)
23 if ((c >= 'A' && c <= 'Z')
24 || (c >='a' && c <= 'z')
25 || (c >='0' && c <= '9')
31 static i8 *builtin_eval(macro_main_t *mm, i8 *varname, i32 complain)
34 i8 *(*fp)(macro_main_t *, i32);
36 p = hash_get_mem(mm->the_builtin_eval_hash, varname);
40 return (*fp)(mm, complain);
43 int clib_macro_unset (macro_main_t * mm, char *name)
48 p = hash_get_pair (mm->the_value_table_hash, name);
54 value = (u8 *) (p->value[0]);
55 hash_unset_mem (mm->the_value_table_hash, name);
62 int clib_macro_set_value (macro_main_t * mm, char *name, char *value)
64 u8 * key_copy, *value_copy;
67 rv = clib_macro_unset (mm, name);
69 key_copy = format (0, "%s%c", name, 0);
70 value_copy = format (0, "%s%c", value, 0);
72 hash_set_mem (mm->the_value_table_hash, key_copy, value_copy);
76 i8 * clib_macro_get_value (macro_main_t * mm, char *name)
80 p = hash_get_mem (mm->the_value_table_hash, name);
88 * eval: takes a string, returns a vector.
89 * looks up $foobar in the variable table.
91 i8 * clib_macro_eval (macro_main_t *mm, i8 *s, i32 complain)
94 i8 *varname, *varvalue;
114 * Make vector with variable name in it.
116 while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '(')))
123 while (*s && *s != ')')
125 vec_add1(varname, *s);
132 vec_add1(varname, *s);
136 vec_add1(varname, 0);
137 /* Look for a builtin, e.g. $my_hostname */
138 if (!(varvalue = builtin_eval(mm, varname, complain)))
140 /* Look in value table */
143 char * tmp = clib_macro_get_value (mm, varname);
145 varvalue = (i8 *) format (0, "%s%c", tmp, 0);
148 /* Look in environment. */
151 char * tmp = getenv (varname);
153 varvalue = (i8 *) format (0, "%s%c", tmp, 0);
155 #endif /* CLIB_UNIX */
159 /* recursively evaluate */
160 ts = clib_macro_eval(mm, varvalue, complain);
162 /* add results to answer */
164 /* Remove NULL termination or the results are sad */
165 _vec_len(rv) = vec_len(rv)-1;
171 clib_warning ("Undefined Variable Reference: %s\n", varname);
172 vec_append(rv, format(0, "UNSET "));
173 _vec_len(rv) = vec_len(rv)-1;
184 * eval: takes a string, returns a vector.
185 * looks up $foobar in the variable table.
187 i8 *clib_macro_eval_dollar (macro_main_t *mm, i8 *s, i32 complain)
192 s2 = (i8 *)format (0, "$(%s)%c", s, 0);
193 rv = clib_macro_eval(mm, s2, complain);
198 void clib_macro_add_builtin (macro_main_t *mm, char *name, void * eval_fn)
200 hash_set_mem(mm->the_builtin_eval_hash, name, (uword) eval_fn);
204 static i8 *eval_hostname (macro_main_t *mm, i32 complain)
207 if (gethostname (tmp, sizeof(tmp)))
208 return ((i8 *) format (0, "gethostname-error%c", 0));
209 return ((i8 *) format (0, "%s%c", tmp, 0));
213 void clib_macro_init(macro_main_t * mm)
215 if (mm->the_builtin_eval_hash != 0)
217 clib_warning ("mm %p already initialized", mm);
221 mm->the_builtin_eval_hash = hash_create_string(0, sizeof(uword));
222 mm->the_value_table_hash = hash_create_string(0, sizeof(uword));
225 hash_set_mem(mm->the_builtin_eval_hash, "hostname",
226 (uword) eval_hostname);
230 void clib_macro_free(macro_main_t * mm)
233 u8 ** strings_to_free = 0;
236 hash_free (mm->the_builtin_eval_hash);
238 hash_foreach_pair (p, mm->the_value_table_hash,
240 vec_add1 (strings_to_free, (u8 *) (p->key));
241 vec_add1 (strings_to_free, (u8 *) (p->value[0]));
244 for (i = 0; i < vec_len (strings_to_free); i++)
245 vec_free (strings_to_free[i]);
246 vec_free (strings_to_free);
247 hash_free (mm->the_value_table_hash);