FD.io VPP  v18.04-17-g3a0d853
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, 2014 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 (macro_main_t * mm, i8 * varname, i32 complain)
32 {
33  uword *p;
34  i8 *(*fp) (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 int
44 clib_macro_unset (macro_main_t * mm, char *name)
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 int
64 clib_macro_set_value (macro_main_t * mm, char *name, char *value)
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 i8 *
95 clib_macro_eval (macro_main_t * mm, i8 * s, i32 complain)
96 {
97  i8 *rv = 0;
98  i8 *varname, *varvalue;
99  i8 *ts;
100 
101  while (*s)
102  {
103  switch (*s)
104  {
105  case '\\':
106  s++;
107  /* fallthrough */
108 
109  default:
110  vec_add1 (rv, *s);
111  s++;
112  break;
113 
114  case '$':
115  s++;
116  varname = 0;
117  /*
118  * Make vector with variable name in it.
119  */
120  while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '(')))
121  {
122 
123  /* handle $(foo) */
124  if (*s == '(')
125  {
126  s++; /* skip '(' */
127  while (*s && *s != ')')
128  {
129  vec_add1 (varname, *s);
130  s++;
131  }
132  if (*s)
133  s++; /* skip ')' */
134  break;
135  }
136  vec_add1 (varname, *s);
137  s++;
138  }
139  /* null terminate */
140  vec_add1 (varname, 0);
141  /* Look for a builtin, e.g. $my_hostname */
142  if (!(varvalue = builtin_eval (mm, varname, complain)))
143  {
144  /* Look in value table */
145  if (!varvalue)
146  {
147  char *tmp = clib_macro_get_value (mm, varname);
148  if (tmp)
149  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
150  }
151 #ifdef CLIB_UNIX
152  /* Look in environment. */
153  if (!varvalue)
154  {
155  char *tmp = getenv (varname);
156  if (tmp)
157  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
158  }
159 #endif /* CLIB_UNIX */
160  }
161  if (varvalue)
162  {
163  /* recursively evaluate */
164  ts = clib_macro_eval (mm, varvalue, complain);
165  vec_free (varvalue);
166  /* add results to answer */
167  vec_append (rv, ts);
168  /* Remove NULL termination or the results are sad */
169  _vec_len (rv) = vec_len (rv) - 1;
170  vec_free (ts);
171  }
172  else
173  {
174  if (complain)
175  clib_warning ("Undefined Variable Reference: %s\n", varname);
176  vec_append (rv, format (0, "UNSET "));
177  _vec_len (rv) = vec_len (rv) - 1;
178 
179  }
180  vec_free (varname);
181  }
182  }
183  vec_add1 (rv, 0);
184  return (rv);
185 }
186 
187 /*
188  * eval: takes a string, returns a vector.
189  * looks up $foobar in the variable table.
190  */
191 i8 *
193 {
194  i8 *s2;
195  i8 *rv;
196 
197  s2 = (i8 *) format (0, "$(%s)%c", s, 0);
198  rv = clib_macro_eval (mm, s2, complain);
199  vec_free (s2);
200  return (rv);
201 }
202 
203 void
204 clib_macro_add_builtin (macro_main_t * mm, char *name, void *eval_fn)
205 {
206  hash_set_mem (mm->the_builtin_eval_hash, name, (uword) eval_fn);
207 }
208 
209 #ifdef CLIB_UNIX
210 static i8 *
212 {
213  char tmp[128];
214  if (gethostname (tmp, sizeof (tmp)))
215  return ((i8 *) format (0, "gethostname-error%c", 0));
216  return ((i8 *) format (0, "%s%c", tmp, 0));
217 }
218 #endif
219 
220 void
222 {
223  if (mm->the_builtin_eval_hash != 0)
224  {
225  clib_warning ("mm %p already initialized", mm);
226  return;
227  }
228 
229  mm->the_builtin_eval_hash = hash_create_string (0, sizeof (uword));
230  mm->the_value_table_hash = hash_create_string (0, sizeof (uword));
231 
232 #ifdef CLIB_UNIX
234 #endif
235 }
236 
237 void
239 {
240  hash_pair_t *p;
241  u8 **strings_to_free = 0;
242  int i;
243 
245 
246  /* *INDENT-OFF* */
248  ({
249  vec_add1 (strings_to_free, (u8 *) (p->key));
250  vec_add1 (strings_to_free, (u8 *) (p->value[0]));
251  }));
252  /* *INDENT-ON* */
253 
254  for (i = 0; i < vec_len (strings_to_free); i++)
255  vec_free (strings_to_free[i]);
256  vec_free (strings_to_free);
258 }
259 
260 /*
261  * fd.io coding-style-patch-verification: ON
262  *
263  * Local Variables:
264  * eval: (c-set-style "gnu")
265  * End:
266  */
i8 * clib_macro_eval_dollar(macro_main_t *mm, i8 *s, i32 complain)
Definition: macros.c:192
void clib_macro_free(macro_main_t *mm)
Definition: macros.c:238
static int macro_isalnum(i8 c)
Definition: macros.c:22
i8 * clib_macro_get_value(macro_main_t *mm, char *name)
Definition: macros.c:79
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:520
int i
#define hash_set_mem(h, key, value)
Definition: hash.h:274
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
uword value[0]
Definition: hash.h:164
int i32
Definition: types.h:81
char i8
Definition: types.h:45
#define hash_get_pair(h, key)
Definition: hash.h:251
uword * the_value_table_hash
Definition: macros.h:34
#define hash_create_string(elts, value_bytes)
Definition: hash.h:675
#define hash_unset_mem(h, key)
Definition: hash.h:290
static i8 * eval_hostname(macro_main_t *mm, i32 complain)
Definition: macros.c:211
void clib_macro_add_builtin(macro_main_t *mm, char *name, void *eval_fn)
Definition: macros.c:204
#define hash_free(h)
Definition: hash.h:309
svmdb_client_t * c
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
#define clib_warning(format, args...)
Definition: error.h:59
i8 * clib_macro_eval(macro_main_t *mm, i8 *s, i32 complain)
Definition: macros.c:95
int clib_macro_unset(macro_main_t *mm, char *name)
Definition: macros.c:44
static i8 * builtin_eval(macro_main_t *mm, i8 *varname, i32 complain)
Definition: macros.c:31
#define vec_append(v1, v2)
Append v2 after v1.
Definition: vec.h:817
int clib_macro_set_value(macro_main_t *mm, char *name, char *value)
Definition: macros.c:64
u64 uword
Definition: types.h:112
uword * the_builtin_eval_hash
Definition: macros.h:33
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
void clib_macro_init(macro_main_t *mm)
Definition: macros.c:221
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:372
#define hash_get_mem(h, key)
Definition: hash.h:268
uword key
Definition: hash.h:161