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/) :(
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
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.
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 ;-)
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
Doesn't look at all like basic, looks like c crap
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");
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
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
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).
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:
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 startNote: 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.
qword,
:t
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 ;-)
Ah, the macro specialists have found the solution. It's a bit macro mania. :t
Gunther
Quote from: Gunther on October 07, 2013, 09:15:34 AMIt's a bit macro mania. :t
where the fun begins :biggrin:
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
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
i remember MS BASIC - lol
you guys are working awfully hard to make ASM not like ASM
am i in the wrong forum ? :redface:
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 ?
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?
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
> 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 :(
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)
nice, qWord :t
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.
procedural macros are generally not expanded in such "call-situations" thus the exclamation mark and the EQU could be omitted.
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.
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 startThe 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:
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
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
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
ENDMTestbed attached. Again, many thanks especially to qWord and Hutch :icon14: