Announcement

Collapse
No announcement yet.

Macro and #IF

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Macro and #IF

    This does not compile:

    Code:
    Macro DoMessage( p1, pMode )
        MacroTemp T
    #If %Def( %DODEBUG )
    #If %DODEBUG = 2
    
    ' code removed, not the issue...
    
    #EndIf
    #EndIf
    End Macro
    
    Function  test() As Long
        DoMessage("", "")
    End Function
    PowerBASIC for Windows
    PB/Win Version 9.01
    Copyright (c) 1996-2009 PowerBasic Inc.

    Error 460 in C:\DOCUME~1\EDWINK\LOCALS~1\TEMP\PD1027\CONST.INC(65:001): Undefined equate

    Line 65: DoMessage("", "")

    Macro Expansion(5): #If %DODEBUG = 2
    hellobasic

  • #2
    Hint:
    #If %DODEBUG = 2
    = "#IF Equate = 2

    Not

    #IF Variable = 2
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    Comment


    • #3
      :confused2:
      hellobasic

      Comment


      • #4
        Code:
        MACRO DoMessage( p1, pMode )
            MACROTEMP T
        #IF %DEF( %DODEBUG ) = 2                '<--- %DEF must be used to test if the equates is correct
        '#If %DODEBUG = 2                       '<--- Can not test value because with #IF then %DEBUG would have to be a variable, not an equates
        
        ' code removed, not the issue...
        
        '#EndIf
        #ENDIF
        END MACRO
        
        FUNCTION  test() AS LONG
            DoMessage("", "")
        END FUNCTION
        
        FUNCTION PBMAIN () AS LONG
        
             Test
        
        END FUNCTION
        Hopefully the commented lines point this error out a bit better.
        Engineer's Motto: If it aint broke take it apart and fix it

        "If at 1st you don't succeed... call it version 1.0"

        "Half of Programming is coding"....."The other 90% is DEBUGGING"

        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

        Comment


        • #5
          Have you actually tested this??

          like:
          Code:
          Macro DoMessage( p1, pMode )
              MacroTemp T
          #If %Def( %DODEBUG ) = 2                '<--- %DEF must be used to test if the equates is correct
          '#If %DODEBUG = 2                       '<--- Can not test value because with #IF then %DEBUG would have to be a variable, not an equates
          blabla
          ' code removed, not the issue...
          
          '#EndIf
          #EndIf
          End Macro
          
          %DODEBUG = 2
          
          Function  test() As Long
              DoMessage("", "")
          End Function
          This compiles fine but shouldn't

          Note that this is the order i'll have but with or without: %DODEBUG = 2 inserted.
          hellobasic

          Comment


          • #6
            Actually I did test it. (Although had to make my changes in previous post to compile).

            So I was a lil surprised you asked if I tested it. My post compiles "As-Is" and my limited experience with macros I could NOT for the life of me figure why it would not compile???

            I set out to show that point, but surprise...surprise...lo and behold, I walk away with more questions than I have answers :confused2:

            So my main question is .... "Why should it NOT compile?"

            Then after that, my sample of WHY it SHOULD compile instead shows my complete confusion :confused2: of why the heck my macros do not change my values, nor do my messageboxes (or print during debug) fire off, but my messagebox outside of raising the macro does work???

            Example below: (Including every overkill comment I could think of)
            Code:
            #DEBUG ERROR ON
            '*** Macro is a powerful text substitution construct that may take a single-line or multi-line format.
            '*** ---> IMPORTANT POINT --->     It generates absolutely no executable code unless it is referenced
            '***
            '***
            '*** For this example I will assume I recompile over and over and just change the equates value of %DODEBUG = something
            '*** %DODEBUG = 0                       'Debug Mode is Off
            '*** %DODEBUG = 1                       'Debug Mode is On
            '*** %DODEBUG = 2                       'Debug Mode is Only on, if some GPF is about to occur, and want to find it and fix it
            '***
            '***
            '*** Uncomment any of the 3 tests you want to check results
            %DODEBUG = 0                       'Debug Mode is Off
            '%DODEBUG = 1                       'Debug Mode is On
            '%DODEBUG = 2                       'Debug Mode is Only on, if some GPF is about to occur, and want to find it and fix it
            
            
            MACRO DoMessage(p1, pMode)              '<--- Variables do not need to be declared??? (So how do I know what p1, and pMode are???..... Best guess p1 = pointer, pMode = Type of pointer? (varptr or strptr)???
                MACROTEMP T                         '<--- Never gets used so not refereced (see IMPORTANT POINT)
            '#IF %DEF(%DODEBUG) = 0                  '<--- %DEF must be used to test if the equates is correct
            '     MSGBOX "%DODEBUG = 0" + p1 + pmode
            '     #DEBUG PRINT "%DODEBUG = 0"
            '#ENDIF
            '#IF %DEF(%DODEBUG) = 1                  '<--- %DEF must be used to test if the equates is correct
            '     MSGBOX "%DODEBUG = 1"
            '     #DEBUG PRINT "%DODEBUG = 1"
            '#ENDIF
            '#IF %DEF(%DODEBUG) = 2                  '<--- %DEF must be used to test if the equates is correct
            '     MSGBOX "%DODEBUG = 2"
            '     #DEBUG PRINT "%DODEBUG = 2"
            '#ENDIF
            #IF %DEF(%DODEBUG) = 0                  '<--- %DEF must be used to test if the equates is correct
                 MSGBOX "%DODEBUG = 0" + p1 + pmode
                 #DEBUG PRINT "%DODEBUG = 0"
                 p1 = 65535
            #ELSEIF %DEF(%DODEBUG) = 1                  '<--- %DEF must be used to test if the equates is correct
                 MSGBOX "%DODEBUG = 1"
                 #DEBUG PRINT "%DODEBUG = 1"
            #ELSEIF %DEF(%DODEBUG) = 2                  '<--- %DEF must be used to test if the equates is correct
                 MSGBOX "%DODEBUG = 2"
                 #DEBUG PRINT "%DODEBUG = 2"
            #ENDIF
            END MACRO
            
            '*** Function to test the macro         '<--- Never got used, so I referenced it for testing
            FUNCTION  test() AS LONG
                 LOCAL p1 AS LONG
                 LOCAL p2 AS STRING
            '    DoMessage("", "")                   '<--- Making this reference should result in the following
                p1 = 42
                p2 = "The Answer is"
                DoMessage(p1, p2)                   '<--- Making this reference should result in the following
                                                    '<--- Function never returns a value (but minor point for this test) :-)
            '---> To Me p1 should now be 65535 because I changed it in the macro, but its not????
                 FUNCTION = p1
            END FUNCTION
            
            '*** Compiling without this will result in
            'PowerBASIC for Windows
            'PB/Win  Version 9.01
            'Copyright (c) 1996-2009 PowerBasic Inc.
            'Venice, Florida USA
            'All Rights Reserved
            '
            'Primary source:  I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas   {29 total lines}
            'Target compilation:  Macros2.exe
            'Compile time:  0.1 seconds, at 34800 lines/minute
            '
            '460 bytes compiled code, 1576 bytes RTLibrary,
            '0 bytes string literals, and 1872 bytes dgroup.
            'Executable stack size:  1048576 bytes.
            'Disk image: 5120 bytes   Memory image: 3448 bytes.
            '
            'Component Files:
            '----------------
            'I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas
            '==============================
            'Compile succeeded at 6:25:18 PM on 5/6/2009
            '
            'PowerBASIC for Windows
            'PB/Win  Version 9.01
            'Copyright (c) 1996-2009 PowerBasic Inc.
            'Venice, Florida USA
            'All Rights Reserved
            '
            'Error 504 in I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas(0:000):  Executable requires WinMain/PBMain function
            '==============================
            'Compile failed at 6:47:04 PM on 5/6/2009
            
            '*** So I added it to compile
            FUNCTION PBMAIN () AS LONG
                 LOCAL Results AS LONG
                 Results = Test                               '<<< Calling this in turn makes a reference to the macro, which in turn expands and inserts the macro code into the "Test" function at compile time
                 MSGBOX STR$(Results)
            END FUNCTION
            Engineer's Motto: If it aint broke take it apart and fix it

            "If at 1st you don't succeed... call it version 1.0"

            "Half of Programming is coding"....."The other 90% is DEBUGGING"

            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

            Comment


            • #7
              There is no serious answer to my question i guess?
              hellobasic

              Comment


              • #8
                The serious answer is, since the nested #IF does not seem to work, don't do that.

                Also, since MACROs generate no executable code, it's really moot if the compiler sees them at compile time, so there's no reason not to define the MACRO unconditionally.

                You could try something like...
                Code:
                #IF NOT %DEF(%DO_DEBUG) 
                    %DO_DEBUG =  0   ' or whatever the default is 
                #ENDIF 
                ' now for all code following, %DO_DEBUG *is* defined, so it can simply be tested.
                
                #IF %DO_DEBUG = 2 
                    MACRO  blah
                    END MACRO 
                #ELSE
                   MACRO blah
                  END MACRO
                #ENDIF
                I have no idea if this will "work"; then again, because MACROs don't generate any code until used, I would not care.

                Frankly, I'd probably just create it as a FUNCTION. If I don't use that function in my program, I would not care about a couple hundred bytes of unused compiled code.


                MCM
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Note my previous post.
                  The macro is declared before the constant or without the constant at all.
                  The function using the macro is at the end of the compile code.

                  macro
                  constant or no constant or incorrect constant-value
                  function

                  Problem is that PB seems to want to verify the constant during the macro code while the macro imo should be expanded and then verified.

                  I can make workarounds but that is besides the point.
                  I was looking for a solution for inside this macro.
                  hellobasic

                  Comment


                  • #10
                    >Note my previous post

                    Mine too: If it don't work, don't do that.

                    >while the macro imo ..

                    "IMO" ===> New Feature Suggestion ===> [email protected]

                    If I dwelt on some of the ways the compiler does things, I'd be on medication for a lot more than my blood pressure.

                    Sometimes you just have to work around and move on.

                    MCM
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      Edwin, here is a serious attempt to answer your implied question. Here is the macro from your example code:

                      Code:
                      Macro DoMessage( p1, pMode )
                          MacroTemp T
                      #If %Def( %DODEBUG )
                      #If %DODEBUG = 2
                      
                      ' code removed, not the issue...
                      
                      #EndIf
                      #EndIf
                      End Macro
                      I think you are assuming that if %DODEBUG is not defined then the compiler should just be skipping over any code that is within that #IF/#ENDIF block. According to the documentation you are correct but you may be running into a problem with the order that things happen and how the compile process works. I believe the equates get replaced before the compiling begins which means that those lines, if %DODEBUG was not defined, would be replaced by:

                      Code:
                      #If %Def(  )
                      #If  = 2
                      If my assumption about your assumption is correct, you feel it should just skip to the second #EndIf in your example and continue compiling. However, the compiler still needs to check each line inside that block to make sure it finds the proper end of that block which will be marked by #ELSEIF, #ELSE or #ENDIF. The first line it encounters while looking for one of these is the #If = 2, which makes no sense to the compiler so it flags it as an error and stops compiling. At least, that is my thinking about how this is happening.

                      You can avoid the problem by either making sure %DODEBUG is always defined and just change the value to whatever you want before compiling. This means you can also get rid of the #If %Def line from your example. Here is what your example would look like doing this:

                      Code:
                      %DODEBUG = 2
                      
                      Macro DoMessage( p1, pMode )
                          MacroTemp T
                      #If %DODEBUG = 2
                      
                      ' code removed, not the issue...
                      
                      #EndIf
                      End Macro
                      Another option is to have multiple versions of the macro for your different debug options and comment them all out except for the one you want to use when you compile. Here is what the code might look like doing this:

                      Code:
                      'Macro DoMessage( p1, pMode )
                      '    MacroTemp T
                      '' code you would use for %DODEBUG = 0
                      'End Macro
                      
                      'Macro DoMessage( p1, pMode )
                      '    MacroTemp T
                      '' code you would use for %DODEBUG = 1
                      'End Macro
                      
                      Macro DoMessage( p1, pMode )
                          MacroTemp T
                      ' code you would use for %DODEBUG = 2
                      End Macro
                      I think the first option is a lot easier as you only need to change the one value each time you compile rather than commenting and uncommenting blocks of multiple lines of code.
                      Jeff Blakeney

                      Comment


                      • #12
                        Thanks,

                        i'll make a request not to check the macro but only the macro extended code.

                        note that i am mostly looking for these solutions, for workarounds.. i'll manage

                        it's similar to topic:
                        http://www.powerbasic.com/support/pb...ad.php?t=40520

                        (I found out that if ... then ... End If is not allowed)
                        hellobasic

                        Comment


                        • #13
                          Cliff, you seem to be having more problems with macros then with the equate issue that Edwin initially brought up. I've added some comments about various parts of your code and comments below.

                          Code:
                          #DEBUG ERROR ON
                          '*** Macro is a powerful text substitution construct that may take a single-line or multi-line format.
                          '*** ---> IMPORTANT POINT --->     It generates absolutely no executable code unless it is referenced
                          '***
                          '***
                          '*** For this example I will assume I recompile over and over and just change the equates value of %DODEBUG = something
                          '*** %DODEBUG = 0                       'Debug Mode is Off
                          '*** %DODEBUG = 1                       'Debug Mode is On
                          '*** %DODEBUG = 2                       'Debug Mode is Only on, if some GPF is about to occur, and want to find it and fix it
                          '***
                          '***
                          '*** Uncomment any of the 3 tests you want to check results
                          %DODEBUG = 0                       'Debug Mode is Off
                          '%DODEBUG = 1                       'Debug Mode is On
                          '%DODEBUG = 2                       'Debug Mode is Only on, if some GPF is about to occur, and want to find it and fix it
                          
                          MACRO DoMessage(p1, pMode)              '<--- Variables do not need to be declared??? (So how do I know what p1, and pMode are???..... Best guess p1 = pointer, pMode = Type of pointer? (varptr or strptr)???
                          Parameters in macros are similar to equate names. They are basically place holders. Whenever a macro is called in your source code, the code from the macro is put into that place in the source and whatever expressions are given for the parameters is put into the code in the places with those names. Your test function would expand to this if you commented out the %DODEBUG = 0 line (I'll get to why it needs to be commented out in a bit):

                          Code:
                          FUNCTION test() AS LONG
                              LOCAL p1 AS LONG
                              LOCAL p2 AS STRING
                          '    DoMessage("", "")
                              p1 = 42
                              p2 = "The Answer is"
                              MSGBOX "%DODEBUG = 0" + p1 + p2
                              p1 = 65535
                              FUNCTION = p1
                          END FUNCTION
                          Continuing through your code the next line is this one which initially came from Edwin's example:

                          Code:
                              MACROTEMP T                         '<--- Never gets used so not refereced (see IMPORTANT POINT)
                          The reason it isn't referenced is that Edwin removed all the code from the macro before posting his code to show the problem he was having. He probably just forgot to remove that line too.

                          Code:
                          #IF %DEF(%DODEBUG) = 0                  '<--- %DEF must be used to test if the equates is correct
                          This will compile but won't work the way you seem to think it will. The %DEF() function returns a true or false value depending on whether the equate name passed to it has been defined or not. %DEF(%DODEBUG) will return either 0 if %DODEBUG is not defined and a non zero value (most likely -1) if it is. In effect, if %DODEBUG is not defined then this statement reduces to #IF 0 = 0 which is fine if you want that code when the equate is not defined but becomes #IF -1 = 0 when %DODEBUG is defined. Basically all of your #IF statements are checking to see if -1 is equal to 0, 1 or 2 so none of them match and you end up with an empty macro.

                          Code:
                               MSGBOX "%DODEBUG = 0" + p1 + pmode
                               #DEBUG PRINT "%DODEBUG = 0"
                               p1 = 65535
                          #ELSEIF %DEF(%DODEBUG) = 1                  '<--- %DEF must be used to test if the equates is correct
                               MSGBOX "%DODEBUG = 1"
                               #DEBUG PRINT "%DODEBUG = 1"
                          #ELSEIF %DEF(%DODEBUG) = 2                  '<--- %DEF must be used to test if the equates is correct
                               MSGBOX "%DODEBUG = 2"
                               #DEBUG PRINT "%DODEBUG = 2"
                          #ENDIF
                          END MACRO
                          
                          '*** Function to test the macro         '<--- Never got used, so I referenced it for testing
                          FUNCTION  test() AS LONG
                               LOCAL p1 AS LONG
                               LOCAL p2 AS STRING
                          '    DoMessage("", "")                   '<--- Making this reference should result in the following
                              p1 = 42
                              p2 = "The Answer is"
                              DoMessage(p1, p2)                   '<--- Making this reference should result in the following
                                                                  '<--- Function never returns a value (but minor point for this test) :-)
                          '---> To Me p1 should now be 65535 because I changed it in the macro, but its not????
                          As I stated above, if %DEF(%DODEBUG) returns a non zero value like -1 when the equate is defined, then the #IF where you set p1 to 65535 never gets used as you don't have an #IF clause that has code for a -1 value. You also need to be very careful about what is passed to a macro. If the code you intended to be used when %DODEBUG = 0 was in place, the MSGBOX would fail because you are adding a numeric data type to a string data type which won't work. Another thing to be careful of is by using the p1 = 65535, you are assuming the p1 is a numeric variable but it could also be the result of a function (ie. VAL("42") or an expression (ie. 32 + 10) and trying to assign a value to the result of an expression will also give you an error.

                          Code:
                               FUNCTION = p1
                          END FUNCTION
                          
                          '*** Compiling without this will result in
                          'PowerBASIC for Windows
                          'PB/Win  Version 9.01
                          'Copyright (c) 1996-2009 PowerBasic Inc.
                          'Venice, Florida USA
                          'All Rights Reserved
                          '
                          'Primary source:  I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas   {29 total lines}
                          'Target compilation:  Macros2.exe
                          'Compile time:  0.1 seconds, at 34800 lines/minute
                          '
                          '460 bytes compiled code, 1576 bytes RTLibrary,
                          '0 bytes string literals, and 1872 bytes dgroup.
                          'Executable stack size:  1048576 bytes.
                          'Disk image: 5120 bytes   Memory image: 3448 bytes.
                          '
                          'Component Files:
                          '----------------
                          'I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas
                          '==============================
                          'Compile succeeded at 6:25:18 PM on 5/6/2009
                          '
                          'PowerBASIC for Windows
                          'PB/Win  Version 9.01
                          'Copyright (c) 1996-2009 PowerBasic Inc.
                          'Venice, Florida USA
                          'All Rights Reserved
                          '
                          'Error 504 in I:\POWERB~4\HELPOT~1\MACROS~1\Macros2.bas(0:000):  Executable requires WinMain/PBMain function
                          '==============================
                          'Compile failed at 6:47:04 PM on 5/6/2009
                          
                          '*** So I added it to compile
                          FUNCTION PBMAIN () AS LONG
                               LOCAL Results AS LONG
                               Results = Test                               '<<< Calling this in turn makes a reference to the macro, which in turn expands and inserts the macro code into the "Test" function at compile time
                               MSGBOX STR$(Results)
                          END FUNCTION
                          You didn't need to add a PBMAIN function. You could have just renamed the function test() to PBMAIN().
                          Jeff Blakeney

                          Comment

                          Working...
                          X