FD.io VPP  v16.06
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 macro_isalnum (i8 c)
22 {
23  if ((c >= 'A' && c <= 'Z')
24  || (c >='a' && c <= 'z')
25  || (c >='0' && c <= '9')
26  || (c == '_'))
27  return 1;
28  return 0;
29 }
30 
31 static i8 *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 clib_macro_unset (macro_main_t * mm, char *name)
44 {
45  hash_pair_t * p;
46  u8 * key, * value;
47 
48  p = hash_get_pair (mm->the_value_table_hash, name);
49 
50  if (p == 0)
51  return 1;
52 
53  key = (u8 *)(p->key);
54  value = (u8 *) (p->value[0]);
56 
57  vec_free (value);
58  vec_free (key);
59  return 0;
60 }
61 
62 int clib_macro_set_value (macro_main_t * mm, char *name, char *value)
63 {
64  u8 * key_copy, *value_copy;
65  int rv;
66 
67  rv = clib_macro_unset (mm, name);
68 
69  key_copy = format (0, "%s%c", name, 0);
70  value_copy = format (0, "%s%c", value, 0);
71 
72  hash_set_mem (mm->the_value_table_hash, key_copy, value_copy);
73  return rv;
74 }
75 
76 i8 * clib_macro_get_value (macro_main_t * mm, char *name)
77 {
78  uword * p;
79 
80  p = hash_get_mem (mm->the_value_table_hash, name);
81  if (p)
82  return (i8 *)(p[0]);
83  else
84  return 0;
85 }
86 
87 /*
88  * eval: takes a string, returns a vector.
89  * looks up $foobar in the variable table.
90  */
91 i8 * clib_macro_eval (macro_main_t *mm, i8 *s, i32 complain)
92 {
93  i8 *rv=0;
94  i8 *varname, *varvalue;
95  i8 *ts;
96 
97  while (*s)
98  {
99  switch(*s)
100  {
101  case '\\':
102  s++;
103  /* fallthrough */
104 
105  default:
106  vec_add1(rv, *s);
107  s++;
108  break;
109 
110  case '$':
111  s++;
112  varname = 0;
113  /*
114  * Make vector with variable name in it.
115  */
116  while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '(')))
117  {
118 
119  /* handle $(foo) */
120  if (*s == '(')
121  {
122  s++; /* skip '(' */
123  while (*s && *s != ')')
124  {
125  vec_add1(varname, *s);
126  s++;
127  }
128  if (*s)
129  s++; /* skip ')' */
130  break;
131  }
132  vec_add1(varname, *s);
133  s++;
134  }
135  /* null terminate */
136  vec_add1(varname, 0);
137  /* Look for a builtin, e.g. $my_hostname */
138  if (!(varvalue = builtin_eval(mm, varname, complain)))
139  {
140  /* Look in value table */
141  if (! varvalue)
142  {
143  char * tmp = clib_macro_get_value (mm, varname);
144  if (tmp)
145  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
146  }
147 #ifdef CLIB_UNIX
148  /* Look in environment. */
149  if (! varvalue)
150  {
151  char * tmp = getenv (varname);
152  if (tmp)
153  varvalue = (i8 *) format (0, "%s%c", tmp, 0);
154  }
155 #endif /* CLIB_UNIX */
156  }
157  if (varvalue)
158  {
159  /* recursively evaluate */
160  ts = clib_macro_eval(mm, varvalue, complain);
161  vec_free(varvalue);
162  /* add results to answer */
163  vec_append(rv, ts);
164  /* Remove NULL termination or the results are sad */
165  _vec_len(rv) = vec_len(rv)-1;
166  vec_free(ts);
167  }
168  else
169  {
170  if (complain)
171  clib_warning ("Undefined Variable Reference: %s\n", varname);
172  vec_append(rv, format(0, "UNSET "));
173  _vec_len(rv) = vec_len(rv)-1;
174 
175  }
176  vec_free(varname);
177  }
178  }
179  vec_add1(rv, 0);
180  return(rv);
181 }
182 
183 /*
184  * eval: takes a string, returns a vector.
185  * looks up $foobar in the variable table.
186  */
188 {
189  i8 *s2;
190  i8 *rv;
191 
192  s2 = (i8 *)format (0, "$(%s)%c", s, 0);
193  rv = clib_macro_eval(mm, s2, complain);
194  vec_free (s2);
195  return (rv);
196 }
197 
198 void clib_macro_add_builtin (macro_main_t *mm, char *name, void * eval_fn)
199 {
200  hash_set_mem(mm->the_builtin_eval_hash, name, (uword) eval_fn);
201 }
202 
203 #ifdef CLIB_UNIX
204 static i8 *eval_hostname (macro_main_t *mm, i32 complain)
205 {
206  char tmp[128];
207  if (gethostname (tmp, sizeof(tmp)))
208  return ((i8 *) format (0, "gethostname-error%c", 0));
209  return ((i8 *) format (0, "%s%c", tmp, 0));
210 }
211 #endif
212 
214 {
215  if (mm->the_builtin_eval_hash != 0)
216  {
217  clib_warning ("mm %p already initialized", mm);
218  return;
219  }
220 
223 
224 #ifdef CLIB_UNIX
225  hash_set_mem(mm->the_builtin_eval_hash, "hostname",
226  (uword) eval_hostname);
227 #endif
228 }
229 
231 {
232  hash_pair_t * p;
233  u8 ** strings_to_free = 0;
234  int i;
235 
237 
239  ({
240  vec_add1 (strings_to_free, (u8 *) (p->key));
241  vec_add1 (strings_to_free, (u8 *) (p->value[0]));
242  }));
243 
244  for (i = 0; i < vec_len (strings_to_free); i++)
245  vec_free (strings_to_free[i]);
246  vec_free (strings_to_free);
248 }
i8 * clib_macro_eval_dollar(macro_main_t *mm, i8 *s, i32 complain)
Definition: macros.c:187
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
void clib_macro_free(macro_main_t *mm)
Definition: macros.c:230
static int macro_isalnum(i8 c)
Definition: macros.c:21
i8 * clib_macro_get_value(macro_main_t *mm, char *name)
Definition: macros.c:76
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define hash_set_mem(h, key, value)
Definition: hash.h:257
uword value[0]
Definition: hash.h:151
int i32
Definition: types.h:81
char i8
Definition: types.h:45
#define clib_warning(format, args...)
Definition: error.h:59
#define hash_get_pair(h, key)
Definition: hash.h:234
uword * the_value_table_hash
Definition: macros.h:33
#define hash_create_string(elts, value_bytes)
Definition: hash.h:609
#define hash_unset_mem(h, key)
Definition: hash.h:263
static i8 * eval_hostname(macro_main_t *mm, i32 complain)
Definition: macros.c:204
void clib_macro_add_builtin(macro_main_t *mm, char *name, void *eval_fn)
Definition: macros.c:198
#define hash_free(h)
Definition: hash.h:269
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
i8 * clib_macro_eval(macro_main_t *mm, i8 *s, i32 complain)
Definition: macros.c:91
int clib_macro_unset(macro_main_t *mm, char *name)
Definition: macros.c:43
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
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:777
int clib_macro_set_value(macro_main_t *mm, char *name, char *value)
Definition: macros.c:62
u64 uword
Definition: types.h:112
uword * the_builtin_eval_hash
Definition: macros.h:32
#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:213
#define hash_foreach_pair(p, v, body)
Definition: hash.h:311
#define hash_get_mem(h, key)
Definition: hash.h:251
uword key
Definition: hash.h:148