News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

#IF

Started by Biterider, June 15, 2018, 06:29:57 AM

Previous topic - Next topic

Biterider

Hi Habran
I can not say for sure until I have a working set of files. My best guress is that it will not be needed.
Biterider

habran

Cod-Father

johnsa

Proposing the following fix:

The core of the issue is that user defined macros are not allowed to received undefined symbols as arguments.
So while IFDEF someUndefinedVar  works, passing that down via a macro will break.

Proposed fix is to allow an undefined symbol to propagate down through the user macro IFF the macro name is "defined"
We can either provide a built-in defined macro, which would be overridden by a user including an INC file such as the Windows headers that define their own defined macro.

Biterider

Hello johnsa
Good to hear from you!  8)
I can not say anything about the assembler internals and if your suggestion will fix the problem. BTW, ML behaves in the same way.
I only want to be sure that the problem is well understood.

In the last few weeks I implemented a super lightweight conditional evaluator using the well known "shunting-yard algorithm" in combination with a tristate truth tables (TRUE, FALSE, ERROR). In this way I was able to evaluate such cases as described above. Eventually such an approach could also solve the problem.

Just my 2 cents.  ;)

Biterider


johnsa

Hi,

I agree that it is definitely expected behaviour, but we can do better.. why not have a proper "defined" macro that just works and can be combined in other expressions.. it would be backwards compatible and still allow any other approach/method to work too.. so .. we'll just do it :)

jj2007

Quote from: johnsa on September 30, 2018, 03:18:46 AMwhy not have a proper "defined" macro

I would suggest @Defined(somesymbol), for consistency with @SubStr(), @CatStr() etc. ML coders could use a workaround:
include \masm32\include\masm32rt.inc

ifndef @Defined
  @Defined MACRO arg
ifdef arg
EXITM <1>
else
EXITM <0>
endif
  ENDM
endif

.data
MyArray dd 25, 18, 23, 17, 9, 2, 6

.code
start:
  if @Defined(MyArray)
print "MyArray is defined", 13, 10
  else
print "MyArray is UNDEFINED", 13, 10
  endif
  if @Defined(NotMyArray)
print "NotMyArray is defined", 13, 10
  else
print "NotMyArray is UNDEFINED", 13, 10
  endif
  inkey "that was easy"
  exit

end start

Biterider

Hi
Sorry, but right now I do not see the point.  ::)
A typical problematic C code line (winerror.h) looks like this

#if defined (_MSC_VER) && (_MSC_VER> = 1020)

The current translation would be

if Defined(_MSC_VER) and (_MSC_VER ge 1020)

If _MSC_VER is not defined here, only the second part of the conditional sentence is problematic because the symbol is undefined and in this case it should not be evaluated because of the use of the logical "and" operator.

I'm using a modified version of Japheth's WinInc defined macro.


  ifndef Defined
    Defined macro x
      ifdef x
        exitm <-1>                      ;-1 to be able to use the 'NOT' operator.
      else                              ;Not(-1) = 0 (FALSE)
        exitm <0>
      endif
    endm
  endif


Maybe you can explain with an example what you want to do.  ;)

Biterider

jj2007

OK, here is a tailored example, with a small modification of the macro:
include \masm32\include\masm32rt.inc

ifndef @Defined
  @Defined MACRO arg
ifdef arg
DefResult equ <arg>
EXITM <arg>
else
DefResult equ <0>
EXITM <0>
endif
  ENDM
endif


.code
start:
  _MSC_VER equ <1020>
  if @Defined(_MSC_VER) ge 1020
print str$(DefResult), 9
print " = _MSC_VER, defined as equal or above 1020", 13, 10, 10
  else
print str$(DefResult), 9
print " = _MSC_VER (UNDEFINED or less than 1020)", 13, 10, 10
  endif

  _MSC_VER equ <1000>
if @Defined(_MSC_VER) ge 1020
print str$(DefResult), 9
print " = _MSC_VER, defined as equal or above 1020", 13, 10, 10
  else
print str$(DefResult), 9
print " = _MSC_VER (UNDEFINED or less than 1020)", 13, 10, 10
  endif

if @Defined(_MSC_NOSUCHVER) ge 1020
print str$(DefResult), 9
print " = _MSC_NOSUCHVER, defined as equal or above 1020", 13, 10, 10
  else
print str$(DefResult), 9
print " = _MSC_NOSUCHVER (UNDEFINED or less than 1020)", 13, 10, 10
  endif

  inkey " "
  exit

end start


Output (identical for UAsm and ML 6.15):
1020     = _MSC_VER, defined as equal or above 1020

1000     = _MSC_VER (UNDEFINED or less than 1020)

0        = _MSC_NOSUCHVER (UNDEFINED or less than 1020)

Biterider

Hi JJ
Thanks for your proposal which works for this example case  :t , but we don't have to forget about all other possible logical combinations (using NOT, AND, OR, XOR) with more than only 1 argument!
The second issue is the C translation. Using this approach, the original conditional sentence has to be analysed and replaced by a modified/reorganized version. This is a very complex and error prone task.
I'm still convinced that there is only one correct way to solve the original issue adding more robustness and flexibility to the assembler as I described before.

@johnsa: can you elaborate your idea a bit more so I can understand what you have in mind. An example would be very helpful.  :idea:

Biterider

johnsa

Sure,

The root of the problem is that internally "IFDEF X" inherently assembles correctly whether X is defined or not, as this is it's purpose. IFDEF only supports a single argument. The problem comes in that if you attempt to create ANY sort of user-level macro like DEFINED(x) the parsing of the macro itself will fail as x is undefined, and undefined symbols are not allowed to be passed to regular macros.
So the idea was to build this macro in, and special case it to allow a direct substitution of the name (ie: x) into the macro body. That way a composite expression should evaluate as planned:

.if defined(x) AND somethingElse EQ 1
.endif

etc.. without any hacks to supports a specific combination or use of AND operator.

Biterider

Hi johnsa
Thanks for your answer. I understand what you want to achieve. Strange for me is, that the "@Defined" macro works also with undefined symbols. The following code demonstrates the point. If you define MY_SYMBOL all is fine, but commenting it out, the second conditional sentence can not be compiled (UASM & ML).

ifndef @Defined
  @Defined macro x
    ifdef x
      exitm <-1>                                      ;-1 to be able to use the 'NOT' operator.
    else                                              ;Not(-1) = 0 (FALSE)
      exitm <0>
    endif
  endm
endif

;MY_SYMBOL equ  5

.code                                         
start:                                         
    if @Defined(MY_SYMBOL)
      echo AAAA
    else
      echo BBBB
    endif

    if not @Defined(MY_SYMBOL)
      echo AAAA
    else
      echo BBBB
    endif

    if @Defined(MY_SYMBOL) and MY_SYMBOL ge 10
      echo CCCC
    else
      echo DDDD
    endif
    ret
end start


Biterider

johnsa

Just an update on this issue for 2.47..

The issue becomes more complex and the reason the 2nd example doesn't work is the expansion of the macro in a conditional assembly expression.
The only real solution to this problem would be to create a new operator (like le, gt etc) to use in expressions which tests for the defined state of a symbol as opposed to the macro approach.

Alternatively, and I've not tried this.. what is the outcome of using OPATTR against the symbol if defined / undefined, that may already work and be usable in an expression ?