Something I have to do a lot is append strings to other strings and while I know how to do it, its still a lot of typing so in conjunction with the szMultiCat procedure that Alexander Yackubtchik (The Svin) wrote , I have popped a small macro that takes a lot of the drudgery out of concntenating strings.


; ------------------------------------------------------
; macro for concantenating strings using the szMultiCat
; procedure written by Alexander Yackubtchik.
;
; USAGE strcat buffer,str1,str2,str3 etc ...
;
; buffer must be large enough to contain all of the
; strings to append. Limit is set by maximum line
; length in MASM.
; ------------------------------------------------------
strcat MACRO arguments:VARARG
txt equ <invoke szMultiCat,> ;; lead string
pcount = 0
FOR arg, <arguments>
pcount = pcount + 1 ;; count arguments
ENDM
% pcount = pcount - 1 ;; dec 1 for 1st arg
txt CATSTR txt,%pcount ;; append number to lead string
FOR arg, <arguments>
txt CATSTR txt, <,ADDR arg> ;; append 'ADDR' + args
ENDM
txt ;; put result in code
ENDM

Regards,

hutch@movsd.com
Posted on 2002-07-01 12:41:27 by hutch--
Good idea - i have done this too. However to avoid bloat i wrote a "C" library functin and modified the macro like so...

strcat macro _dest:req, _src:req, _list:vararg

ifb <_list>
invok lstrcat, _dest, _src
else
invok _strcat, _dest, $argc(_src, _list), _src, _list
endif
endm

then i modified my strcpy macro also

strcpy macro _dest:req, _src:req, _list:vararg
ifnb <_list>
push eax
invok lstrcpy, _dest, _src
pop eax
invok _strcat, _dest, $argc(_list), _list
else
invok lstrcpy, _dest, _src
endif
endm

** the push/pop eax is needed to allow for a macro function in the list

strcpy dest, v1, v2, func(v3)

the lstrcpy call would trash eax - the return vlue.


Actually i have wrappers for all the str*** functions (strcmp, strdel ...) because they're so common.
Posted on 2002-07-01 13:27:09 by gfalen
I have had a bit of time to play with this macro and added a few others. The extra 2 are str$() and hex$() ALA basic commands. I have modified the strcat macro so it will take either the name of a string buffer or ADDR name so that it can accept other macros that return ADDR name.

The macro is case sensitive with ADDR and as mentioned before, the MASM line limit is the limit on how much can be appended to the original string buffer.

It can do stuff like,


mov buffer[0], 0
strcat buffer, SADD("hInstance = "), hex$(hInstance), SADD(" hex")
invoke SetWindowText,hWnd,ADDR buffer


Regards,

hutch@movsd.com


; ------------------------------------------------------
; macro for concantenating strings using the szMultiCat
; procedure written by Alexander Yackubtchik.
;
; USAGE strcat buffer,str1,str2,str3 etc ...
;
; buffer must be large enough to contain all of the
; strings to append. Limit is set by maximum line
; length in MASM.
; ------------------------------------------------------
strcat MACRO arguments:VARARG
txt equ <invoke szMultiCat,> ;; lead string
pcount = 0
FOR arg, <arguments>
pcount = pcount + 1 ;; count arguments
ENDM
% pcount = pcount - 1 ;; dec 1 for 1st arg
txt CATSTR txt,%pcount ;; append number to lead string
FOR arg, <arguments>
IF @InStr(1,<arg>,<ADDR>) ne 0
txt CATSTR txt, <,arg>
ELSE
txt CATSTR txt, <,ADDR arg> ;; append 'ADDR' + args
ENDIF
ENDM
txt ;; put result in code
ENDM

; ----------------------------------------------------------
; function position macros that takes a DWORD parameter and
; returns the address of the buffer that holds the result
; ----------------------------------------------------------
str$ MACRO DDvalue
LOCAL rvstring
.data
rvstring db 20 dup (0)
.code
invoke dwtoa,DDvalue,ADDR rvstring
EXITM <ADDR rvstring>
ENDM

hex$ MACRO DDvalue
LOCAL rvstring
.data
rvstring db 12 dup (0)
.code
invoke dw2hex,DDvalue,ADDR rvstring
EXITM <ADDR rvstring>
ENDM

Posted on 2002-07-01 17:27:46 by hutch--
When you go to write another macro that calls a C routine you gotta get the argcount again. And when you wanna write strcmp, strdel, strstr... you're gonna have to do more for/endm loops. Better you should have some "helper" macros to do all this routine housekeeping for you. Like

$argc() - returns arg count
invok - combines args and "invokes" function
@invok - "function" form of invok

... just to name a few. Also it woulld'nt hurt to have invoke check for "literals" and declare them on the fly.

In the recent thtead on "switch/case" i posted my 2 macro files - masm.inc & macs32.inc. They have all this in them and much more. Let me know if you don't have them. I'll repost & you can scavenge from there and save yourself a lot of typing.
Posted on 2002-07-01 18:14:55 by gfalen
Greg,

I think your idea is a good one but I have to keep in mind the people who are going to use the macros and interdependent macros are very hard for beginners to understand.

I know there is a trend around to HIDE as much as possible from the programmer but it is exactly the opposite of what I designed in the first place with MASM32 to reveal as much as possible to programmers who are using it.

Much of what many people hate about the modern C++ include files is thw near imppossibility of tracking how they hang together because of the multiple dependencies.

What I am inclined to do with macros is keep them as self contained as possible so that each one makes sense in itself. The excellent set of macros you designed for the "switch/case" functionality is a self contained set of macros that do not have any great interdependence on outside functions.

Regards,

hutch@movsd.com
Posted on 2002-07-02 02:09:56 by hutch--