LCOV - code coverage report
Current view: top level - vppinfra - macros.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 5 131 3.8 %
Date: 2023-10-26 01:39:38 Functions: 1 13 7.7 %

          Line data    Source code
       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
      22           0 : macro_isalnum (i8 c)
      23             : {
      24           0 :   if ((c >= 'A' && c <= 'Z')
      25           0 :       || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '_'))
      26           0 :     return 1;
      27           0 :   return 0;
      28             : }
      29             : 
      30             : static i8 *
      31           0 : 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           0 :   p = hash_get_mem (mm->the_builtin_eval_hash, varname);
      37           0 :   if (p == 0)
      38           0 :     return 0;
      39           0 :   fp = (void *) (p[0]);
      40           0 :   return (*fp) (mm, complain);
      41             : }
      42             : 
      43             : __clib_export int
      44           0 : clib_macro_unset (clib_macro_main_t * mm, char *name)
      45             : {
      46             :   hash_pair_t *p;
      47             :   u8 *key, *value;
      48             : 
      49           0 :   p = hash_get_pair (mm->the_value_table_hash, name);
      50             : 
      51           0 :   if (p == 0)
      52           0 :     return 1;
      53             : 
      54           0 :   key = (u8 *) (p->key);
      55           0 :   value = (u8 *) (p->value[0]);
      56           0 :   hash_unset_mem (mm->the_value_table_hash, name);
      57             : 
      58           0 :   vec_free (value);
      59           0 :   vec_free (key);
      60           0 :   return 0;
      61             : }
      62             : 
      63             : __clib_export int
      64           0 : clib_macro_set_value (clib_macro_main_t * mm, char *name, char *value)
      65             : {
      66             :   u8 *key_copy, *value_copy;
      67             :   int rv;
      68             : 
      69           0 :   rv = clib_macro_unset (mm, name);
      70             : 
      71           0 :   key_copy = format (0, "%s%c", name, 0);
      72           0 :   value_copy = format (0, "%s%c", value, 0);
      73             : 
      74           0 :   hash_set_mem (mm->the_value_table_hash, key_copy, value_copy);
      75           0 :   return rv;
      76             : }
      77             : 
      78             : i8 *
      79           0 : clib_macro_get_value (clib_macro_main_t * mm, char *name)
      80             : {
      81             :   uword *p;
      82             : 
      83           0 :   p = hash_get_mem (mm->the_value_table_hash, name);
      84           0 :   if (p)
      85           0 :     return (i8 *) (p[0]);
      86             :   else
      87           0 :     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           0 : clib_macro_eval (clib_macro_main_t * mm, i8 * s, i32 complain, u16 level,
      96             :                  u16 max_level)
      97             : {
      98           0 :   i8 *rv = 0;
      99             :   i8 *varname, *varvalue;
     100             :   i8 *ts;
     101             : 
     102           0 :   if (level >= max_level)
     103             :     {
     104           0 :       if (complain)
     105           0 :         clib_warning ("circular definition, level %d", level);
     106           0 :       return (i8 *) format (0, " CIRCULAR ");
     107             :     }
     108             : 
     109           0 :   while (*s)
     110             :     {
     111           0 :       switch (*s)
     112             :         {
     113           0 :         case '\\':
     114           0 :           s++;
     115             :           /* fallthrough */
     116             : 
     117           0 :         default:
     118           0 :           vec_add1 (rv, *s);
     119           0 :           s++;
     120           0 :           break;
     121             : 
     122           0 :         case '$':
     123           0 :           s++;
     124           0 :           varname = 0;
     125             :           /*
     126             :            * Make vector with variable name in it.
     127             :            */
     128           0 :           while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '(')))
     129             :             {
     130             : 
     131             :               /* handle $(foo) */
     132           0 :               if (*s == '(')
     133             :                 {
     134           0 :                   s++;          /* skip '(' */
     135           0 :                   while (*s && *s != ')')
     136             :                     {
     137           0 :                       vec_add1 (varname, *s);
     138           0 :                       s++;
     139             :                     }
     140           0 :                   if (*s)
     141           0 :                     s++;        /* skip ')' */
     142           0 :                   break;
     143             :                 }
     144           0 :               vec_add1 (varname, *s);
     145           0 :               s++;
     146             :             }
     147             :           /* null terminate */
     148           0 :           vec_add1 (varname, 0);
     149             :           /* Look for a builtin, e.g. $my_hostname */
     150           0 :           if (!(varvalue = builtin_eval (mm, varname, complain)))
     151             :             {
     152             :               /* Look in value table */
     153           0 :               if (!varvalue)
     154             :                 {
     155           0 :                   i8 *tmp = clib_macro_get_value (mm, (char *) varname);
     156           0 :                   if (tmp)
     157           0 :                     varvalue = (i8 *) format (0, "%s%c", tmp, 0);
     158             :                 }
     159             : #ifdef CLIB_UNIX
     160             :               /* Look in environment. */
     161           0 :               if (!varvalue)
     162             :                 {
     163           0 :                   char *tmp = getenv ((char *) varname);
     164           0 :                   if (tmp)
     165           0 :                     varvalue = (i8 *) format (0, "%s%c", tmp, 0);
     166             :                 }
     167             : #endif /* CLIB_UNIX */
     168             :             }
     169           0 :           if (varvalue)
     170             :             {
     171             :               /* recursively evaluate */
     172           0 :               ts = clib_macro_eval (mm, varvalue, complain, level + 1,
     173             :                                     max_level);
     174           0 :               vec_free (varvalue);
     175             :               /* add results to answer */
     176           0 :               vec_append (rv, ts);
     177             :               /* Remove NULL termination or the results are sad */
     178           0 :               vec_set_len (rv, vec_len (rv) - 1);
     179           0 :               vec_free (ts);
     180             :             }
     181             :           else
     182             :             {
     183           0 :               if (complain)
     184           0 :                 clib_warning ("Undefined Variable Reference: %s\n", varname);
     185           0 :               vec_append (rv, format (0, "UNSET "));
     186           0 :               vec_set_len (rv, vec_len (rv) - 1);
     187             :             }
     188           0 :           vec_free (varname);
     189             :         }
     190             :     }
     191           0 :   vec_add1 (rv, 0);
     192           0 :   return (rv);
     193             : }
     194             : 
     195             : /*
     196             :  * eval: takes a string, returns a vector.
     197             :  * looks up $foobar in the variable table.
     198             :  */
     199             : __clib_export i8 *
     200           0 : clib_macro_eval_dollar (clib_macro_main_t *mm, i8 *s, i32 complain)
     201             : {
     202             :   i8 *s2;
     203             :   i8 *rv;
     204             : 
     205           0 :   s2 = (i8 *) format (0, "$(%s)%c", s, 0);
     206           0 :   rv = clib_macro_eval (mm, s2, complain, 0 /* level */ , 8 /* max_level */ );
     207           0 :   vec_free (s2);
     208           0 :   return (rv);
     209             : }
     210             : 
     211             : __clib_export void
     212           0 : clib_macro_add_builtin (clib_macro_main_t * mm, char *name, void *eval_fn)
     213             : {
     214           0 :   hash_set_mem (mm->the_builtin_eval_hash, name, (uword) eval_fn);
     215           0 : }
     216             : 
     217             : #ifdef CLIB_UNIX
     218             : static i8 *
     219           0 : eval_hostname (clib_macro_main_t * mm, i32 complain)
     220             : {
     221             :   char tmp[128];
     222           0 :   if (gethostname (tmp, sizeof (tmp)))
     223           0 :     return ((i8 *) format (0, "gethostname-error%c", 0));
     224           0 :   return ((i8 *) format (0, "%s%c", tmp, 0));
     225             : }
     226             : #endif
     227             : 
     228             : __clib_export void
     229         575 : clib_macro_init (clib_macro_main_t * mm)
     230             : {
     231         575 :   if (mm->the_builtin_eval_hash != 0)
     232             :     {
     233           0 :       clib_warning ("mm %p already initialized", mm);
     234           0 :       return;
     235             :     }
     236             : 
     237         575 :   mm->the_builtin_eval_hash = hash_create_string (0, sizeof (uword));
     238         575 :   mm->the_value_table_hash = hash_create_string (0, sizeof (uword));
     239             : 
     240             : #ifdef CLIB_UNIX
     241        1150 :   hash_set_mem (mm->the_builtin_eval_hash, "hostname", (uword) eval_hostname);
     242             : #endif
     243             : }
     244             : 
     245             : __clib_export void
     246           0 : clib_macro_free (clib_macro_main_t * mm)
     247             : {
     248             :   hash_pair_t *p;
     249           0 :   u8 **strings_to_free = 0;
     250             :   int i;
     251             : 
     252           0 :   hash_free (mm->the_builtin_eval_hash);
     253             : 
     254             :   /* *INDENT-OFF* */
     255           0 :   hash_foreach_pair (p, mm->the_value_table_hash,
     256             :   ({
     257             :     vec_add1 (strings_to_free, (u8 *) (p->key));
     258             :     vec_add1 (strings_to_free, (u8 *) (p->value[0]));
     259             :   }));
     260             :   /* *INDENT-ON* */
     261             : 
     262           0 :   for (i = 0; i < vec_len (strings_to_free); i++)
     263           0 :     vec_free (strings_to_free[i]);
     264           0 :   vec_free (strings_to_free);
     265           0 :   hash_free (mm->the_value_table_hash);
     266           0 : }
     267             : 
     268             : typedef struct
     269             : {
     270             :   u8 *name;
     271             :   u8 *value;
     272             : } name_sort_t;
     273             : 
     274             : static int
     275           0 : name_compare (void *a1, void *a2)
     276             : {
     277           0 :   name_sort_t *ns1 = a1;
     278           0 :   name_sort_t *ns2 = a2;
     279             : 
     280           0 :   return strcmp ((char *) ns1->name, (char *) ns2->name);
     281             : }
     282             : 
     283             : 
     284             : __clib_export u8 *
     285           0 : format_clib_macro_main (u8 * s, va_list * args)
     286             : {
     287           0 :   clib_macro_main_t *mm = va_arg (*args, clib_macro_main_t *);
     288           0 :   int evaluate = va_arg (*args, int);
     289             :   hash_pair_t *p;
     290           0 :   name_sort_t *nses = 0, *ns;
     291             :   int i;
     292             : 
     293             :   /* *INDENT-OFF* */
     294           0 :   hash_foreach_pair (p, mm->the_value_table_hash,
     295             :   ({
     296             :     vec_add2 (nses, ns, 1);
     297             :     ns->name = (u8 *)(p->key);
     298             :     ns->value = (u8 *)(p->value[0]);
     299             :   }));
     300             :   /* *INDENT-ON* */
     301             : 
     302           0 :   if (vec_len (nses) == 0)
     303           0 :     return s;
     304             : 
     305           0 :   vec_sort_with_function (nses, name_compare);
     306             : 
     307           0 :   for (i = 0; i < vec_len (nses); i++)
     308             :     {
     309           0 :       s = format (s, "%-20s", nses[i].name);
     310           0 :       if (evaluate == 0)
     311           0 :         s = format (s, "%s\n", nses[i].value);
     312             :       else
     313             :         {
     314           0 :           u8 *rv = (u8 *) clib_macro_eval_dollar (mm, (i8 *) nses[i].name,
     315             :                                                   0 /* no complain */ );
     316           0 :           s = format (s, "%s\n", rv);
     317           0 :           vec_free (rv);
     318             :         }
     319             :     }
     320           0 :   return s;
     321             : }
     322             : 
     323             : 
     324             : /*
     325             :  * fd.io coding-style-patch-verification: ON
     326             :  *
     327             :  * Local Variables:
     328             :  * eval: (c-set-style "gnu")
     329             :  * End:
     330             :  */

Generated by: LCOV version 1.14