The MASM Forum

General => The Laboratory => Topic started by: jj2007 on October 06, 2013, 04:20:08 AM

Title: If condition Then action one-liner
Post by: jj2007 on October 06, 2013, 04:20:08 AM
Some Basic dialects know this construct: If MyVar==1 Then MyVar++

include \masm32\include\masm32rt.inc

_If MACRO arg:VARARG
LOCAL is
  is INSTR <arg>, <Then>
  ife is
   .err @CatStr(<*** no Then in line >, %@Line, < ***>)
  else
   % echo condition=[@SubStr(<arg>, 1, is-2)]
   .if @SubStr(<arg>, 1, is-1)
      @SubStr(<arg>, is+5)
   .endif
  endif
ENDM
.code
start:
   or ebx, -1
   mov edi, 123
   _If !!!!(ebx==+1 && edi==999) Then print "Condition A is FALSE", 13, 10
   _If ebx==-1 && edi==123 Then print "Condition B is TRUE", 13, 10

   inkey "ok?"
   exit
end start


Drawbacks:
- doesn't look like assembler :biggrin:
- negation requires FOUR exclamation marks  ::)
- not possible with JWasm (https://sourceforge.net/p/jwasm/bugs/) :(
Title: Re: If condition Then action one-liner
Post by: Gunther on October 06, 2013, 09:56:18 AM
Jochen,

Quote from: jj2007 on October 06, 2013, 04:20:08 AM
Drawbacks:
- doesn't look like assembler :biggrin:
- negation requires FOUR exclamation marks  ::)
- not possible with JWasm (https://sourceforge.net/p/jwasm/bugs/) :(

But the idea is nice.

Gunther
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 06, 2013, 10:52:39 AM
Looks fine for basic, I wonder if you can use a text word for the negation ?

I confess I prefer the block form and use it in basic but there are situations where the one line form is useful.
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 06, 2013, 05:47:56 PM
Quote from: hutch-- on October 06, 2013, 10:52:39 AM
Looks fine for basic, I wonder if you can use a text word for the negation ?
No luck with ex1 equ ! or similar. The beast really wants 4 exclamation marks :(

QuoteI confess I prefer the block form and use it in basic but there are situations where the one line form is useful.
There are coders who prefer to see as much as possible (many lines on screen, dense code, complex macros...), others prefer to see the detail, and even add empty lines containing only comments.
Likewise, some people prefer the monolithic 10,000 lines source, while others split it into one-hundred include files. What is better? What is more productive?
It is a bit like the known difference between those who need a complete diagram to understand a problem, while others need a page of text instead. Interesting question in itself, it would merit a thread in the Soap Box ;-)
Title: Re: If condition Then action one-liner
Post by: dedndave on October 06, 2013, 06:15:18 PM
some of those personal preferences stem from how the programmer got started
when i started out, DEBUG was one of my best tools - lol
i was used to seeing each instruction with no macros or symbols
Title: Re: If condition Then action one-liner
Post by: jimg on October 07, 2013, 01:52:55 AM
Doesn't look at all like basic, looks like c crap
Title: Re: If condition Then action one-liner
Post by: japheth on October 07, 2013, 02:01:24 AM
Quote from: jimg on October 07, 2013, 01:52:55 AM
Doesn't look at all like basic, looks like c crap

:icon_mrgreen:

No, C is way, way, way more elegant:


i == 1 ? printf("i is 1\n") : printf("i is not 1\n");
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 07, 2013, 02:28:53 AM
Quote from: jimg on October 07, 2013, 01:52:55 AM
Doesn't look at all like basic, looks like c crap
Can't speak for many BASIC dialects but those that I'm familiar with do have the one-liner:

VBA:
  If result = 1 Then MsgBox "hi"
Gfa:
  IF IsZoomed(hDlg&) THEN ~ShowWindow(hDlg&,SW_RESTORE)
PowerBasic:
  IF BeepOn THEN BEEP
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 07, 2013, 05:36:07 AM
JJ,

The notation is ugly but it seems to work.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    iff MACRO arg1,arg2
      .if arg1
        arg2
      .endif
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    mov eax, 1
    iff eax !!= 1,<mov eax, 3>
    print ustr$(eax),13,10

    mov eax, 1
    iff eax == 1,<mov eax, 3>
    print ustr$(eax),13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


Now here is a variant that is truly disgusting.  :icon_mrgreen:



  ; mi - multiple instruction

    mi MACRO arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arga,argb,argc,argd,arge,argf,argg
      arg1
      arg2
      arg3
      arg4
      arg5
      arg6
      arg7
      arg8
      arg9
      arga
      argb
      argc
      argd
      arge
      argf
      argg
    ENDM

    mi <.if eax !!= 1>,<mov eax, 1>,<add eax, 1>,<add eax, 1>,<add eax, 1>,<.endif>
    print ustr$(eax),13,10

Title: Re: If condition Then action one-liner
Post by: Paulo on October 07, 2013, 07:04:45 AM
hutch

How about _If ? (like jj2007 originally wrote).
I find that _If just looks better then iff .

Like in C/C++, where an underscore followed by an uppercase letter is reserved for macros and libs (I think).
Title: Re: If condition Then action one-liner
Post by: qWord on October 07, 2013, 07:32:19 AM
include \masm32\include\masm32rt.inc

when EQU .until !
then macro action:VARARG
LOCAL lbl
    jmp lbl
    .repeat
       
        action
        .break
    lbl:
    EXITM <>
endm

.code
main proc
   
    when TRUE then (mov esi,1234)
    mov edi,123

    when (eax == eax && esi >= edi) then (print "foo^2",13,10)
   
    when (rv(GetTickCount) != 0 && eax < -1 ) then (print "GTC is in some range",13,10)

    inkey
    exit
main endp
end main

:biggrin:
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 07, 2013, 08:42:27 AM
Quote from: hutch-- on October 07, 2013, 05:36:07 AM
The notation is ugly but it seems to work.

Hutch,
It's almost as elegant as the Chinese version ;)

But still, I like staying as close as possible to existing Basic syntax - and I found a solution for the bloody !!!! problem:

include \masm32\include\masm32rt.inc

_If MACRO arg:VARARG
LOCAL is
  is INSTR <arg>, <Then>
  ife is
   .err @CatStr(<*** no Then in line >, %@Line, < ***>)
  else
   ifidni @SubStr(<arg>, 1, 3), <not>
      .if !@SubStr(<arg>, 5, is-5)
         @SubStr(<arg>, is+5)
      .endif
   else
      .if @SubStr(<arg>, 1, is-1)
         @SubStr(<arg>, is+5)
      .endif
   endif
  endif
ENDM

.code
start:   or ebx, -1
   mov edi, 123
   _If not (ebx==1 && edi==999) Then print "Condition A is FALSE", 13, 10
   _If ebx==-1 && edi==123 Then print "Condition B is TRUE", 13, 10
   inkey "ok?"
   exit
end start


Note: The _If not ... variant requires brackets only if there is more than one condition, i.e. _If not eax Then ... is valid syntax. The positive _If ... Then variant never requires brackets.
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 07, 2013, 08:45:36 AM
qword,

:t
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 07, 2013, 09:08:17 AM
Neat trick, qWord :t
    nops 4
    when ebx==edi then (mov esi,1234)
    nops 4
    _If ebx==edi Then mov esi,1234
    nops 4

00401001       ³.  90                  nop
00401002       ³.  90                  nop
00401003       ³.  90                  nop
00401004       ³.  90                  nop
00401005       ³. EB 07               jmp short 0040100E
00401007       ³>  BE D2040000         mov esi, 4D2
0040100C       ³. EB 04               jmp short 00401012
0040100E       ³>  3BDF                cmp ebx, edi
00401010       ³. 75 F5               jne short 00401007
00401012       ³>  90                  nop
00401013       ³.  90                  nop
00401014       ³.  90                  nop
00401015       ³.  90                  nop
00401016       ³.  3BDF                cmp ebx, edi
00401018       ³. 75 05               jne short 0040101F
0040101A       ³.  BE D2040000         mov esi, 4D2
0040101F       ³>  90                  nop
00401020       ³.  90                  nop
00401021       ³.  90                  nop
00401022       ³.  90                  nop


Could be a little bit shorter under the hood, though ;-)
Title: Re: If condition Then action one-liner
Post by: Gunther on October 07, 2013, 09:15:34 AM
Ah, the macro specialists have found the solution. It's a bit macro mania. :t

Gunther
Title: Re: If condition Then action one-liner
Post by: qWord on October 07, 2013, 09:46:41 AM
Quote from: Gunther on October 07, 2013, 09:15:34 AMIt's a bit macro mania. :t
where the fun begins  :biggrin:
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 07, 2013, 12:01:00 PM
JJ,

No pain, no gain. Humour aside, the ugly notation for MASM code does exactly what I want a single line macro to do and it is tidy in code output terms.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    slen PROTO pstr:DWORD

    iph MACRO arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8
      .if arg1
        arg2
        arg3
        arg4
        arg5
        arg6
        arg7
        arg8
      .endif
    ENDM

    nsf MACRO                       ;; no stack frame
      OPTION PROLOGUE:NONE
      OPTION EPILOGUE:NONE
    ENDM

    sfo MACRO                       ;; stack frame on
      OPTION PROLOGUE:PrologueDef
      OPTION EPILOGUE:EpilogueDef
    ENDM

    mi MACRO arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arga,argb,argc,argd,arge,argf, \
       argg,argh,argi,argj,argk,argl,argm,argn,argo,argp,argq,argr,args,argt,argu,argv,argw
      arg1
      arg2
      arg3
      arg4
      arg5
      arg6
      arg7
      arg8
      arg9
      arga
      argb
      argc
      argd
      arge
      argf
      argg
      argh
      argi
      argj
      argk
      argl
      argm
      argn
      argo
      argp
      argq
      argr
      args
      argt
      argu
      argv
      argw
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    mov eax, 1
    iph eax !!= 1,<mov eax, 3>

    mov eax, 1
    iph eax == 1,<xor eax, eax>,<add eax, 10>

    mov eax, 2
    mi <.if eax !!= 1>,<xor eax, eax>,<add eax, 1>,<add eax, 1>,<add eax, 1>,<.endif>

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    mi <nsf>,<slen proc pstr:DWORD>,<mov eax,[esp+4]>,<sub eax,1>,<lbl:>,<add eax,1>,\
       <cmp DWORD PTR [eax],0>,<jne lbl>,<sub eax,[esp+4]>,<retn>,<slen endp>,<sfo>

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


the /EP listing output shows the result.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    mov eax, 1
      .if eax != 1
        mov eax, 3
      .endif

    mov eax, 1
      .if eax == 1
        xor eax, eax
        add eax, 10
      .endif

    mov eax, 2
      .if eax != 1
      xor eax, eax
      add eax, 1
      add eax, 1
      add eax, 1
      .endif

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

      OPTION PROLOGUE:NONE
      OPTION EPILOGUE:NONE
      slen proc pstr:DWORD
      mov eax,[esp+4]
      sub eax,1
      lbl:
      add eax,1
      cmp DWORD PTR [eax],0
      jne lbl
      sub eax,[esp+4]
      retn
      slen endp
      OPTION PROLOGUE:PrologueDef
      OPTION EPILOGUE:EpilogueDef

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Title: Re: If condition Then action one-liner
Post by: dedndave on October 07, 2013, 12:33:25 PM
i remember MS BASIC - lol
you guys are working awfully hard to make ASM not like ASM
am i in the wrong forum ?   :redface:
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 07, 2013, 01:32:02 PM
Now I have a question for anyone old enough to know the answer, I from time to time find a problem that MASM will execute components of a macro out of order based on how it reads the macro line of text. Long ago i saw a technique to force MASM to read the data in order but I equally long ago forgot what it was.

Anyone have any idea about how this is done ?
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 07, 2013, 04:49:40 PM
Quote from: dedndave on October 07, 2013, 12:33:25 PM
you guys are working awfully hard to make ASM not like ASM
am i in the wrong forum ?   :redface:
You are in the right forum, Dave. Despite my heavy use of macros, my biggest source (RichMasm) is still >80% "pure" assembler. But without macros there would be a lot of really boring and repetitive stuff... it's a question of productivity.
Can you imagine a long WndProc with endless .if ... .elseif series instead of Switch ... Case? Or worse, jxx instead of HLL syntax? No thanks 8)

Quote from: hutch-- on October 07, 2013, 01:32:02 PMMASM will execute components of a macro out of order based on how it reads the macro line of text.

Not sure what you mean: Execution before the line as in .elseif rv(instr()))==0? Or expansion with the % operator?
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 07, 2013, 05:32:51 PM
I have attached a test file stripped down to show the characteristic. It is not the macro that I need to fix, I already have a number of ways of doing this, its just that I have forgotten how to force the order of the macros so the left one is executed first.

IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
                      To see the /EP output run "makeit.bat"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

      .486                                      ; create 32 bit code
      .model flat, stdcall                      ; 32 bit memory model
      option casemap :none                      ; case sensitive

    ifc MACRO arg1,arg2,arg3:VARARG
        echo cif here
      .if arg1
      arg2
    ENDM

    then MACRO arg1:VARARG
        echo then here
        arg1
      ;; .endif
      EXITM <>
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    ret

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

  ; ----------------------------------------
  ; with the following macro call the "then"
  ; macro is written BEFORE the "ifc" macro
  ; ----------------------------------------
    ifc eax == 1, then(add eax, 2)

    .endif      ; <<<< this is added because the code is written before the .IF in the 1st macro

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 07, 2013, 05:41:23 PM
> ifc eax == 1, then(add eax, 2)

Hutch,
you mean something like
  mov eax, chr$(("pTest=")
  print eax, str$(eax)  ; please print eax first, then str$(eax)
??
Not possible afaik :(
Title: Re: If condition Then action one-liner
Post by: qWord on October 08, 2013, 12:33:47 AM
Quote from: hutch-- on October 07, 2013, 05:32:51 PMhow to force the order of the macros so the left one is executed first
prefixing the macro name by an exclamation mark prevent expansion:

    ifc MACRO arg1,args:VARARG
      echo arg1,args
      .if arg1
       args
      .endif
    ENDM
    then MACRO args:VARARG
      echo args
       args
      EXITM <>
    ENDM
    ifc eax == 1,!then(add eax, 2)
Title: Re: If condition Then action one-liner
Post by: dedndave on October 08, 2013, 12:51:04 AM
nice, qWord   :t
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 08, 2013, 01:14:17 AM
Thanks, that is what I was after.

This seems to work OK, with the equate for "then" the macro parser started to squark on the comma inside the "then" result so I went back to angle brackets and removed the EXITM <>.


    ifc MACRO arg1,arg2:VARARG
      .if arg1
      arg2
    ENDM

    then equ <!thn>

    thn MACRO arg1:VARARG
      arg1
      .endif
    ENDM

; -----------

    ifc eax == 1, then <add eax, 2>


I think to get what JJ was after you would need to parse the entire line but at least this comes close for a simple pair of macros.
Title: Re: If condition Then action one-liner
Post by: qWord on October 08, 2013, 01:29:10 AM
procedural macros are generally not expanded in such "call-situations"  thus the exclamation mark and the EQU could be omitted.
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 08, 2013, 02:14:36 AM
Yep, works fine.

This line produces the following code expansion.

ifc eax == 1, then <add eax, 2>


/EP list file.

      .if eax == 1
      add eax,2
      .endif


PS: I like the "when" semantic, reads nicely and makes sense.
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 08, 2013, 10:54:25 AM
Quote from: qWord on October 08, 2013, 01:29:10 AM
procedural macros are generally not expanded in such "call-situations"  thus the exclamation mark and the EQU could be omitted.

I stumbled over a very odd behaviour when using the exclamation mark:

include \masm32\include\masm32rt.inc
If_ MACRO arg:VARARG        ; If_ not eax Then inc ecx : add ecx, ...
LOCAL is, args
  is INSTR <arg>, <Then>
  ife is
        .err @CatStr(<*** no Then in line >, %@Line, < ***>)
  else
        args CATSTR @SubStr(<arg>, is+5), <: >
        ifidni @SubStr(<arg>, 1, 3), <not>
                .if !@SubStr(<arg>, 5, is-5)
                        If_2 args
                .endif
        else
                .if @SubStr(<arg>, 1, is-1)
                        If_2 args
                .endif
        endif
  endif
ENDM

If_2 MACRO args
LOCAL args, cc, is
  cc INSTR args, <:>
  is=1
  WHILE cc gt is
        tmp$ SUBSTR args, is, cc-is
        % echo tmp$
        tmp$
        is=cc+1
        cc INSTR is, args, <:>
  ENDM
ENDM

fakestr$ MACRO arg
  pushad
  print "## "
  popad
  exitm chr$("x")
ENDM

.code
start:
        m2m eax, 103
        If_ eax Then dec eax: dec eax: dec eax: print str$(eax), " - should be 100", 13, 10

        m2m eax, 103
        If_ eax Then dec eax: dec eax: dec eax: print !fakestr$(eax), " - should be one '#' and one 'x'", 13, 10

        inkey "ok?"

        exit

end start


The first If_ eax Then dec eax... delivers 103 instead of 100 because of macro expansion happening before even the test of the condition; which clearly demonstrates that one must be very careful with using functional macros after the Then.

The second one shows the odd behaviour. As the text says, you should see one '#' and one 'x' - and that is what you see indeed when you take away the exclamation mark...

Source attached (pure Masm32).

P.S.: Apart from this, the If_ ... Then macro works like a charm, it will be included in the next MasmBasic update. To be consistent with For_ ... Next (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1185), I moved the underscore behind the If. For multiple instruction, the colon is now being used, as in most Basic dialects. Thanks for all the helpful remarks :icon14:
Title: Re: If condition Then action one-liner
Post by: qWord on October 08, 2013, 12:49:39 PM
the problem is that the text macro "args" contains the macro call to fakestr$(): whenever this text macro is used as argument for the string functions, MASM expand it as far as possible. That is the reason why the fake macro is called so often. The problem could be solved by directly passing the input of If_ to the submacros:
If_ MACRO arg:VARARG        ; If_ not eax Then inc ecx : add ecx, ...
LOCAL is, args
  is INSTR <arg>, <Then>
  ife is
        .err @CatStr(<*** no Then in line >, %@Line, < ***>)
  else
        args CATSTR @SubStr(<arg>, is+5), <: >
        ifidni @SubStr(<arg>, 1, 3), <not>
                .if !@SubStr(<arg>, 5, is-5)
                        If_2 %is+5,<&arg: >
                .endif
        else
                .if @SubStr(<arg>, 1, is-1)
                        If_2 %is+5,<&arg: >
                .endif
        endif
  endif
ENDM

If_2 MACRO pos,args
LOCAL cc, is
echo pos,args
  cc INSTR pos,<&args>, <:>
  is=pos
  WHILE cc gt is
        tmp$ SUBSTR <&args>, is, cc-is
        tmp$
        is=cc+1
        cc INSTR is, <&args>, <:>
  ENDM
ENDM


BTW: If_2: the local variable args has the same name as the macro parameter
Title: Re: If condition Then action one-liner
Post by: hutch-- on October 08, 2013, 03:02:15 PM
JJ,

I think this one does the job.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    eql textequ <==>        ;; equal
    neq textequ <!!=>       ;; not equal
    ltn textequ <!<>        ;; less than
    gtt textequ <!>>        ;; greater than
    gte textequ <!>=>       ;; greater or equal
    lte textequ <!<=>       ;; less than or equal

    lnif MACRO arg:VARARG
      LOCAL larg
      LOCAL rarg
      LOCAL cpoz

      cpoz INSTR 1, <arg>, <then>

      IF cpoz eq 0
        .ERR
        echo -------------------------------------
        echo "then" expected with "lnif" statement
        echo -------------------------------------
        EXITM
      ENDIF

      larg SUBSTR <arg>, 1, cpoz-2
      rarg SUBSTR <arg>, cpoz+4

      .if larg
        rarg
      .endif

    ENDM


    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    lnif eax eql 1 then add eax, 1
    lnif eax neq 1 then add eax, 1
    lnif eax ltn 1 then add eax, 1
    lnif eax gtt 1 then add eax, 1
    lnif eax gte 1 then add eax, 1
    lnif eax lte 1 then add eax, 1

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: If condition Then action one-liner
Post by: jj2007 on October 08, 2013, 08:15:36 PM
Quote from: qWord on October 08, 2013, 12:49:39 PM
the problem is that the text macro "args" contains the macro call to fakestr$(): whenever this text macro is used as argument for the string functions, MASM expand it as far as possible.

Thanxalot, qWord - that did the trick :t

@Hutch: Thanks, I took a slightly different road now, but your code inspired me to find a solution for JWasm's @SubStr() bug.

Here is the final version (now included in MasmBasic (http://masm32.com/board/index.php?topic=94.0)) - works with Masm 6.15 ... 10.0 and JWasm:

If_ MACRO arg:VARARG
LOCAL is, cond
  is INSTR <arg>, <Then>
  ife is
   .err @CatStr(<*** no Then in line >, %@Line, < ***>)
  else
   ifidni @SubStr(<arg>, 1, 3), <not>
      cond SUBSTR <arg>, 5, is-5   ; If_ not eax==3 || eax==4 Then inc eax
      .if !(cond)
         If_2 %is+5, <arg: >
      .endif
   else
      cond SUBSTR <arg>, 1, is-1   ; If_ eax Then inc eax : print !str$(eax)
      .if cond
         If_2 %is+5, <arg: >
      .endif
   endif
  endif
ENDM

If_2 MACRO pos, args
LOCAL cc, is
  cc INSTR pos, <args>, <:>
  is=pos
  WHILE cc gt is
        tmp$ SUBSTR <args>, is, cc-is
        tmp$
        is=cc+1
        cc INSTR is, <args>, <:>
  ENDM
ENDM


Testbed attached. Again, many thanks especially to qWord and Hutch :icon14: