Announcement

Collapse
No announcement yet.

Macro and #IF

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

  • Jeff Blakeney
    replied
    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().

    Leave a comment:


  • Edwin Knoppert
    replied
    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)

    Leave a comment:


  • Jeff Blakeney
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    >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

    Leave a comment:


  • Edwin Knoppert
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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

    Leave a comment:


  • Edwin Knoppert
    replied
    There is no serious answer to my question i guess?

    Leave a comment:


  • Cliff Nichols
    replied
    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

    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 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

    Leave a comment:


  • Edwin Knoppert
    replied
    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
    [B]blabla[/B]
    ' 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.

    Leave a comment:


  • Cliff Nichols
    replied
    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.

    Leave a comment:


  • Edwin Knoppert
    replied

    Leave a comment:


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

    Not

    #IF Variable = 2

    Leave a comment:


  • Edwin Knoppert
    started a topic Macro and #IF

    Macro and #IF

    This does not compile:

    Code:
    Macro DoMessage( p1, pMode )
        MacroTemp T
    #If %Def( %DODEBUG )
    [B]#If %DODEBUG = 2[/B]
    
    ' 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
Working...
X