Nested switch statment using X-macros

64 views Asked by At
#define LIST_D1(val, mask, _lc, _UC, comment, parentDictId) \
    __BTN(val 1, mask ~0, _lc##cred_amazon_mws_token, _UC##CRED_AMAZON_MWS_TOKEN, comment N_("Amazon MWS Auth Token"), parentDictId 170) \
    __BTN(val 2, mask ~0, _lc##cred_git_token, _UC##CRED_GIT_TOKEN, comment N_("Git Token"), parentDictId 170) \
    /*end-of-list*/

#define LIST_D2(val, mask, _lc, _UC, comment, parentDictId) \
    __BTN(val 1, mask ~0, _lc##cred_amazon_mws_token, _UC##CRED_AMAZON_MWS_TOKEN, comment N_("Amazon MWS Auth Token"), parentDictId 172) \
    __BTN(val 2, mask ~0, _lc##cred_git_token, _UC##CRED_GIT_TOKEN, comment N_("Git Token"), parentDictId 172) \
    /*end-of-list*/

#define LIST_D3(val, mask, _lc, _UC, comment, parentDictId) \
    __BTN(val 1, mask ~0, _lc##aspp_cn, _UC##ASPP_CN, comment N_("China (CN)"), parentDictId 171) \
    __BTN(val 2, mask ~0, _lc##aspp_jp, _UC##ASPP_JP, comment N_("Japan (JP)"), parentDictId 171) \
    /*end-of-list*/
/* __BTN(val, mask, name, shortname, internal_name, comment) */
#define list_dicts \
    __BTN(172, 0, DICT_CRED, Credentials and Secrets, D1, N_("Credentials and Secrets"))    \
    __BTN(171, 0, DICT_EUPP, Passport - EU, D2, N_("Passport - EU"))                     \
    __BTN(170, 0, DICT_USDL, Drivers License (US), D2, N_("Drivers License U.S."))       \
    /* end of list */

static const char *get_name(int did, int id) {

    char *a;
    switch (did) {
#define __BTN(val, mask, name, shortname, internal_name, comment) \
      case val: \
          return #internal_name; \
          break;
          list_dicts
#undef __BTN
   }
   return NULL;
}
int main() {

    int id = 170;

    printf("I got: %s\n", get_name(id, 1));
    return 0;
}

With the above code and X-macros, I am able to achieve this, which works well with simple switch statements. Here is output of

gcc code.c -E

static const char *get_name(int did, int id) {

 char *a;
     switch (did) {
   case 172: return "D1"; break; case 171: return "D2"; break; case 170: return "D2"; break;

  }
 return ((void *)0)
           ;
}

My goal is to create something like this using X-macros. I've never used X-macros before. I am open to changing the original macro definitions to make this work. If not X-macros, how to efficiently achieve this?

 static const char *get_name(int did, int id) {

 char *a;
 switch (did) {
   case 172:
     /* LIST_D1 using #internal_name "D1" or parentDictId number 172 */
     switch (id) {
           case 1:
               return #comment;
           case 2:
               return #comment;
           
      } 
      break; 
   case 171:
     ...
     break; 
  case 170:
     ...
     break;
 }
 return NULL;
}
1

There are 1 answers

1
John Bollinger On

My goal is to [expand nested] Xmacros.

It is possible to do this, but it gets extremely messy, extremely fast. If you want to proceed that way then you will need to use different names for the X macro in the different lists. It may also benefit you to receive the names of those macros as arguments to the list macros. Not only does that allow you to have multiple X macros defined at the same time and used in the same code, but it also would allow them to be parameterized differently (on a per-target-list basis).

I have used X macros along the lines described above, but I'm not going to give an example because you almost surely would be better off doing differently. For example, you could consider

  • putting your data into arrays and writing a function whose behavior is driven by those arrays. Or

  • writing a separate program to generate the wanted code for you, instead of relying on the C preprocessor.