FD.io VPP  v21.01.1
Vector Packet Processing
macros.c
Go to the documentation of this file.
1 /*
2  * macros.c - a simple macro expander
3  *
4  * Copyright (c) 2010-2020 Cisco and/or its affiliates.
5  *
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:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17 */
18 
19 #include <vppinfra/macros.h>
20 
21 static inline int
23 {
24  if ((c >= 'A' && c <= 'Z')
25  || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '_'))
26  return 1;
27  return 0;
28 }
29 
30 static i8 *
31 builtin_eval (clib_macro_main_t * mm, i8 * varname, i32 complain)
32 {
33  uword *p;
34  i8 *(*fp) (clib_macro_main_t *, i32);
35 
36  p = hash_get_mem (mm->the_builtin_eval_hash, varname);
37  if (p == 0)
38  return 0;
39  fp = (void *) (p[0]);
40  return (*fp) (mm, complain);
41 }
42 
43 __clib_export int
45 {
46  hash_pair_t *p;
47  u8 *key, *value;
48 
49  p = hash_get_pair (mm->the_value_table_hash, name);
50 
51  if (p == 0)
52  return 1;
53 
54  key = (u8 *) (p->key);
55  value = (u8 *) (p->value[0]);
57 
58  vec_free (value);
59  vec_free (key);
60  return 0;
61 }
62 
63 __clib_export int
65 {
66  u8 *key_copy, *value_copy;
67  int rv;
68 
69  rv = clib_macro_unset (mm, name);
70 
71  key_copy = format (0, "%s%c", name, 0);
72  value_copy = format (0, "%s%c", value, 0);
73 
74  hash_set_mem (mm->the_value_table_hash, key_copy, value_copy);
75  return rv;
76 }
77 
78 i8 *
80 {
81  uword *p;
82 
83  p = hash_get_mem (mm->the_value_table_hash, name);
84  if (p)
85  return (i8 *) (p[0]);
86  else
87  return 0;
88 }
89 
90 /*
91  * eval: takes a string, returns a vector.
92  * looks up $foobar in the variable table.
93  */
94 __clib_export i8 *
95 clib_macro_eval (clib_macro_main_t * mm, i8 * s, i32 complain, u16 level,
96  u16 max_level)
97 {
98  i8 *rv = 0;
99  i8 *varname, *varvalue;
100  i8 *ts;
101 
102  if (level >= max_level)
103  {
104  if (complain)
105  clib_warning ("circular definition, level %d", level);
106  return (i8 *) format (0, " CIRCULAR ");
107  }
108 
109  while (*s)
110  {
111  switch (*s)
112  {
113  case '\\':
114  s++;
115  /* fallthrough */
116 
117  default:
118  vec_add1 (rv, *s);
119  s++;
120  break;
121 
122  case '$':
123  s++;
124  varname = 0;
125  /*
126  * Make vector with variable name in it.
127  */
128  while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '(')))
129  {
130 
131  /* handle $(foo) */
132  if (*s == '(')
133  {
134  s++; /* skip '(' */
135  while (*s && *s != ')')
136  {
137  vec_add1 (varname, *s);
138  s++;
139  }
140  if (*s)
141  s++; /* skip ')' */
142  break;
143  }
144  vec_add1 (varname, *s);
145  s++;
146  }
147  /* null terminate */
148  vec_add1 (varname, 0);
149  /* Look for a builtin, e.g. $my_hostname */
150  if (!(varvalue = builtin_eval (mm, varname, complain)))
151  {
152  /* Look in value table */
153  if (!varvalue)
154  {
155  i8 *tmp = clib_macro_get_value (mm, (char *) varname);
156  if (tmp)
157  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
158  }
159 #ifdef CLIB_UNIX
160  /* Look in environment. */
161  if (!varvalue)
162  {
163  char *tmp = getenv ((char *) varname);
164  if (tmp)
165  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
166  }
167 #endif /* CLIB_UNIX */
168  }
169  if (varvalue)
170  {
171  /* recursively evaluate */
172  ts = clib_macro_eval (mm, varvalue, complain, level + 1,
173  max_level);
174  vec_free (varvalue);
175  /* add results to answer */
176  vec_append (rv, ts);
177  /* Remove NULL termination or the results are sad */
178  _vec_len (rv) = vec_len (rv) - 1;
179  vec_free (ts);
180  }
181  else
182  {
183  if (complain)
184  clib_warning ("Undefined Variable Reference: %s\n", varname);
185  vec_append (rv, format (0, "UNSET "));
186  _vec_len (rv) = vec_len (rv) - 1;
187 
188  }
189  vec_free (varname);
190  }
191  }
192  vec_add1 (rv, 0);
193  return (rv);
194 }
195 
196 /*
197  * eval: takes a string, returns a vector.
198  * looks up $foobar in the variable table.
199  */
200 i8 *
202 {
203  i8 *s2;
204  i8 *rv;
205 
206  s2 = (i8 *) format (0, "$(%s)%c", s, 0);
207  rv = clib_macro_eval (mm, s2, complain, 0 /* level */ , 8 /* max_level */ );
208  vec_free (s2);
209  return (rv);
210 }
211 
212 __clib_export void
213 clib_macro_add_builtin (clib_macro_main_t * mm, char *name, void *eval_fn)
214 {
215  hash_set_mem (mm->the_builtin_eval_hash, name, (uword) eval_fn);
216 }
217 
218 #ifdef CLIB_UNIX
219 static i8 *
221 {
222  char tmp[128];
223  if (gethostname (tmp, sizeof (tmp)))
224  return ((i8 *) format (0, "gethostname-error%c", 0));
225  return ((i8 *) format (0, "%s%c", tmp, 0));
226 }
227 #endif
228 
229 __clib_export void
231 {
232  if (mm->the_builtin_eval_hash != 0)
233  {
234  clib_warning ("mm %p already initialized", mm);
235  return;
236  }
237 
238  mm->the_builtin_eval_hash = hash_create_string (0, sizeof (uword));
239  mm->the_value_table_hash = hash_create_string (0, sizeof (uword));
240 
241 #ifdef CLIB_UNIX
243 #endif
244 }
245 
246 __clib_export void
248 {
249  hash_pair_t *p;
250  u8 **strings_to_free = 0;
251  int i;
252 
254 
255  /* *INDENT-OFF* */
257  ({
258  vec_add1 (strings_to_free, (u8 *) (p->key));
259  vec_add1 (strings_to_free, (u8 *) (p->value[0]));
260  }));
261  /* *INDENT-ON* */
262 
263  for (i = 0; i < vec_len (strings_to_free); i++)
264  vec_free (strings_to_free[i]);
265  vec_free (strings_to_free);
267 }
268 
269 typedef struct
270 {
273 } name_sort_t;
274 
275 static int
276 name_compare (void *a1, void *a2)
277 {
278  name_sort_t *ns1 = a1;
279  name_sort_t *ns2 = a2;
280 
281  return strcmp ((char *) ns1->name, (char *) ns2->name);
282 }
283 
284 
285 __clib_export u8 *
286 format_clib_macro_main (u8 * s, va_list * args)
287 {
288  clib_macro_main_t *mm = va_arg (*args, clib_macro_main_t *);
289  int evaluate = va_arg (*args, int);
290  hash_pair_t *p;
291  name_sort_t *nses = 0, *ns;
292  int i;
293 
294  /* *INDENT-OFF* */
296  ({
297  vec_add2 (nses, ns, 1);
298  ns->name = (u8 *)(p->key);
299  ns->value = (u8 *)(p->value[0]);
300  }));
301  /* *INDENT-ON* */
302 
303  if (vec_len (nses) == 0)
304  return s;
305 
307 
308  for (i = 0; i < vec_len (nses); i++)
309  {
310  s = format (s, "%-20s", nses[i].name);
311  if (evaluate == 0)
312  s = format (s, "%s\n", nses[i].value);
313  else
314  {
315  u8 *rv = (u8 *) clib_macro_eval_dollar (mm, (i8 *) nses[i].name,
316  0 /* no complain */ );
317  s = format (s, "%s\n", rv);
318  vec_free (rv);
319  }
320  }
321  return s;
322 }
323 
324 
325 /*
326  * fd.io coding-style-patch-verification: ON
327  *
328  * Local Variables:
329  * eval: (c-set-style "gnu")
330  * End:
331  */
__clib_export void clib_macro_free(clib_macro_main_t *mm)
Definition: macros.c:247
static int macro_isalnum(i8 c)
Definition: macros.c:22
uword * the_value_table_hash
Definition: macros.h:34
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
#define hash_set_mem(h, key, value)
Definition: hash.h:275
__clib_export i8 * clib_macro_eval(clib_macro_main_t *mm, i8 *s, i32 complain, u16 level, u16 max_level)
Definition: macros.c:95
unsigned char u8
Definition: types.h:56
uword value[0]
Definition: hash.h:165
__clib_export int clib_macro_unset(clib_macro_main_t *mm, char *name)
Definition: macros.c:44
__clib_export void clib_macro_init(clib_macro_main_t *mm)
Definition: macros.c:230
__clib_export u8 * format_clib_macro_main(u8 *s, va_list *args)
Definition: macros.c:286
description fragment has unexpected format
Definition: map.api:433
#define hash_get_pair(h, key)
Definition: hash.h:252
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
#define hash_unset_mem(h, key)
Definition: hash.h:291
static i8 * eval_hostname(clib_macro_main_t *mm, i32 complain)
Definition: macros.c:220
unsigned short u16
Definition: types.h:57
#define hash_free(h)
Definition: hash.h:310
signed char i8
Definition: types.h:45
i8 * clib_macro_eval_dollar(clib_macro_main_t *mm, i8 *s, i32 complain)
Definition: macros.c:201
svmdb_client_t * c
static i8 * builtin_eval(clib_macro_main_t *mm, i8 *varname, i32 complain)
Definition: macros.c:31
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define clib_warning(format, args...)
Definition: error.h:59
string name[64]
Definition: ip.api:44
signed int i32
Definition: types.h:77
u8 value
Definition: qos.api:54
uword * the_builtin_eval_hash
Definition: macros.h:33
__clib_export int clib_macro_set_value(clib_macro_main_t *mm, char *name, char *value)
Definition: macros.c:64
#define vec_append(v1, v2)
Append v2 after v1.
Definition: vec.h:890
u8 * value
Definition: macros.c:272
typedef key
Definition: ipsec_types.api:86
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:373
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
static int name_compare(void *a1, void *a2)
Definition: macros.c:276
#define hash_get_mem(h, key)
Definition: hash.h:269
u8 * name
Definition: macros.c:271
uword key
Definition: hash.h:162
__clib_export void clib_macro_add_builtin(clib_macro_main_t *mm, char *name, void *eval_fn)
Definition: macros.c:213
i8 * clib_macro_get_value(clib_macro_main_t *mm, char *name)
Definition: macros.c:79