Help with #defines at compile time.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • dissectcode2
    New Member
    • Apr 2009
    • 32

    Help with #defines at compile time.

    hi! I have these two different macros; one is a scaled down version of the other. I have a header where I need to choose which macro to use for every module in my firmware (~100 modules), at compile time. Here is an example of what I'm trying to do, but I know this macro doesn't work because I can't have multiple directives on the same line...

    Code:
    enum DEBUG_LEVEL{ none, medium, high }
    
    #define DBG(module, debug_level)    \
      #if (__MODULE__) == (module)      \
        #if (MODULEMATCH==1)            \
        #error "already matched!"       \
        #endif                          \
                                        \
        #define debug DEBUGS(debug_level) \  // this will just choose which debug macro for that module to expand inline
        #define MODULEMATCH=1;          \
      #endif
    
    DBG(moduleA, 0);
    DBG(moduleB, 1);

    where __MODULE__ is a -D flag in the makefile for which module is being compiled...

    I must do this in a header so I can easily go back and change levels as needed, and everything is in one spot. Do anyone know how to modify this so it will work? thank you
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    A macro is a compile time substitution. Processing, like using == from C can't work becuase that's C and not a preprocessor command.

    Most likely you will need:

    #ifdef (ModuleA)

    #endif

    #ifdef (ModuleB)

    #endif

    where ModuleA and ModuleB are flags, either - or #define.

    The fact you have 100 modules should not be an issue.

    Comment

    • donbock
      Recognized Expert Top Contributor
      • Mar 2008
      • 2427

      #3
      I don't have my reference book handy, but I'm pretty sure the compiler standard explicitly prohibits preprocessor conditionals like #if within the body of a macro definition. I'm also pretty sure you are also prohibited from defining one macro within the body of another.

      What exactly does __MODULE__ expand to? Perhaps its expansion can be pasted onto some prefix characters to form a legal name.

      Are you using C or C++?

      Comment

      • dissectcode2
        New Member
        • Apr 2009
        • 32

        #4
        thanks both.

        your suggestion donbock of prefixing __MODULE__ is brilliant and i was trying that but it seems that when I use ## to combine __MODULE__, which is the name of the module like moduleA (just plain, not a string) with something like ID_ there is a prescendence issue and it doesn't work:

        Code:
        #define __MODULE__ moduleA
        #define MODULE (ID_ ## __MODULE__)
         
        // so want to test that ID_moduleA is defined..
        #if defined (ID_moduleA)
        ...
        #endif
        
        
        #define ID_moduleA DEBUG_LEVEL1
        
        
        //where...
        #define DEBUG_LEVEL1 1

        MODULE just turns out to be ID__MODULE__ !


        do you know a trick to make it work?

        Comment

        • donbock
          Recognized Expert Top Contributor
          • Mar 2008
          • 2427

          #5
          I'm not aware of any way to construct the name of a macro in the #define statement.

          What's the executive summary for what you're trying to accomplish?

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            OK you can use == in preprocessor directives, but it only understands integers there is no string comparisons and floating point is right out.

            So

            Code:
            #define LEVEL 7
            
            #if LEVEL == 7
            // do stuff
            #endif
            Works. Also note that the value of an undefined symbol used in this sort of construct is 0

            The preprocessor is simple, as Don says nested preprocessor statements of any kind are not allowed, each statement must stand by itself.

            You want to change what is going on dependent on your module so let us assume a few modules call them network, ui and datastore. Remember everything must be integers, that is all the preprocessor can handle so first we define some symbols to assign integer values to our module names

            Code:
            // Remember don't use 0 an undefined symbol has 
            // the value 0 so it will match everything that 
            // is not defined
            #define MODULE_DEFAULT     1
            #define MODULE_NETWORK     2
            #define MODULE_UI          3
            #define MODULE_DATASTORE   4
            So we will need to know what the current module is, that will be defined on the compiler command line so we need to check that it is write some code for that

            Code:
            // Symbol MODULE contains the current module check 
            // that is does and if not set to default
            #if !defined(MODULE)
            #define MODULE DEFAULT_MODULE
            #endif
            
            // If you prefer you can just error
            #if !defined(MODULE)
            #error MODULE not defined
            #endif
            So now the symbol MODULE is defined and should be set to one of our module definitions, we need some debug levels

            Code:
            // Again don't use 0
            #define DEBUG_LEVEL_ALL      1
            #define DEBUG_LEVEL_LOTS     2
            #define DEBUG_LEVEL_SOME     3
            #define DEBUG_LEVEL_A_LITTLE 4
            #define DEBUG_LEVEL_NONE     5
            Now we can test our current module and set our debug level

            Code:
            // Set symbol DEBUG_LEVEL to contain the level 
            // of debugging require for this module
            #if MODULE == MODULE_DEFAULT
            #define DEBUG_LEVEL DEBUG_LEVEL_A_LITTLE
            #elif MODULE == MODULE_NETWORK 
            #define DEBUG_LEVEL DEBUG_LEVEL_LOTS
            #elif MODULE == MODULE_UI
            #define DEBUG_LEVEL DEBUG_LEVEL_SOME
            #elif MODULE == MODULE_DATASTORE
            #define DEBUG_LEVEL DEBUG_NONE
            #else
            #error MODULE not defined correctly
            #endif
            This works because MODULE has been defined to one of our module name symbols that have a numerical value so we are just testing numerical values.

            So putting it all together you get

            Code:
            // Define module names to numbers
            // Remember don't use 0 an undefined symbol has 
            // the value 0 so it will match everything that 
            // is not defined
            #define MODULE_DEFAULT     1
            #define MODULE_NETWORK     2
            #define MODULE_UI          3
            #define MODULE_DATASTORE   4
            
            
            // Symbol MODULE contains the current module check 
            // that it is not blank if it is set to default
            #if !defined(MODULE)
            #define MODULE DEFAULT_MODULE
            #endif
            
            // Define our debug levels again don't use 0
            #define DEBUG_LEVEL_ALL      1
            #define DEBUG_LEVEL_LOTS     2
            #define DEBUG_LEVEL_SOME     3
            #define DEBUG_LEVEL_A_LITTLE 4
            #define DEBUG_LEVEL_NONE     5
            
            
            // Set symbol DEBUG_LEVEL to contain the level 
            // of debugging required based on the module
            #if MODULE == MODULE_DEFAULT
            #define DEBUG_LEVEL DEBUG_LEVEL_A_LITTLE
            #elif MODULE == MODULE_NETWORK 
            #define DEBUG_LEVEL DEBUG_LEVEL_LOTS
            #elif MODULE == MODULE_UI
            #define DEBUG_LEVEL DEBUG_LEVEL_SOME
            #elif MODULE == MODULE_DATASTORE
            #define DEBUG_LEVEL DEBUG_NONE
            #else
            #error MODULE not defined correctly
            #endif
            
            // Note in this last section rather than #defining a 
            // symbol you could set the value of a const variable 
            // (more preferable in C++)
            And on the compiler command line you put a switch similar to -DMODULE=MODULE_ UI


            Remember the Preprocessor is not your friend but sometimes you can force it to do what you want :D
            Last edited by Banfa; Dec 8 '11, 02:54 PM.

            Comment

            Working...