The fn, fnc, rv, and rvc macros break the uni$ macro

Started by MichaelW, February 02, 2011, 11:57:11 AM

Previous topic - Next topic

MichaelW

The ML error return is of the form:

Assembling: test.asm
test.asm(126) : error A2065: expected : comma
uni$(51): Macro Called From
  test.asm(126): Main Line Code
test.asm(126) : fatal error A1008: unmatched macro nesting
uni$(68): Macro Called From
  test.asm(126): Main Line Code


The problems are with line 177 and 194 of ucmacros.asm:

% FORC arg, <nustr>
. . .
ENDM


My test code:

;=========================================================================
    include \masm32\include\masm32rt.inc
    include \masm32\macros\ucmacros.asm
;=========================================================================

;------------------------------
; Substituted 'uarg' for 'arg'
;------------------------------

    _uni$ MACRO text@@:VARARG

        LOCAL addstr1
        LOCAL iname

        ustrng1 equ <>
        ustrng2 equ <>
        ustrng3 equ <>

        addstr1 equ <>
        addstr2 equ <>
        addstr3 equ <>
        cnt@@_$ = 0

        slen@@ SIZESTR <text@@>

     ;; ------------------------------------------------
     ;; test for errors in length or missing quotations
     ;; ------------------------------------------------
        if slen@@ gt 118
          echo -----------------------
          echo *** STRING TOO LONG ***
          echo -----------------------
        .ERR
        EXITM <>
        endif

        qot1 SUBSTR <text@@>,1,1
        IFDIF qot1,<">
          echo -----------------------------
          echo *** MISSING LEADING QUOTE ***
          echo -----------------------------
        .ERR
        EXITM <>
        ENDIF

        qot2 SUBSTR <text@@>,slen@@,1
        IFDIF qot2,<">
          echo ------------------------------
          echo *** MISSING TRAILING QUOTE ***
          echo ------------------------------
        .ERR
        EXITM <>
        ENDIF

      ;; ------------------------------------------------
      ;; loop through the characters in the string adding
      ;; them in a WORD formatted form to the end of each
      ;; string depending on the length.
      ;; ------------------------------------------------
        nustr SUBSTR <text@@>,2,slen@@-2
      % FORC uarg, <nustr>
          if cnt@@_$ lt 1
            addstr1 CATSTR addstr1,<">,<uarg>,<">
          elseif cnt@@_$ lt 40
            addstr1 CATSTR addstr1,<,">,<uarg>,<">

          elseif cnt@@_$ lt 41
            addstr2 CATSTR addstr2,<">,<uarg>,<">
          elseif cnt@@_$ lt 80
            addstr2 CATSTR addstr2,<,">,<uarg>,<">

          elseif cnt@@_$ lt 81
            addstr3 CATSTR addstr3,<">,<uarg>,<">
          elseif cnt@@_$ lt 120
            addstr3 CATSTR addstr3,<,">,<uarg>,<">
          endif
          cnt@@_$ = cnt@@_$ + 1
        ENDM

        .data
      ;; ------------------------------------------------
      ;; The following three blocks append the 00 to the
      ;; end of the string depending on how long it is
      ;; ------------------------------------------------
        if cnt@@_$ lt 41
        addstr1 CATSTR addstr1,<,00>
        endif
          ustrng1 CATSTR ustrng1,<iname>,< dw >,addstr1
          ustrng1
        if cnt@@_$ lt 41
          .code
          goto mclbl
        endif

        if cnt@@_$ lt 81
          addstr2 CATSTR addstr2,<,00>
        endif
          ustrng2 CATSTR ustrng2,< dw >,addstr2
          ustrng2
        if cnt@@_$ lt 81
          .code
          goto mclbl
        endif

        addstr3 CATSTR addstr3,<,00>
        ustrng3 CATSTR ustrng3,< dw >,addstr3
        ustrng3
          .code

        :mclbl

        EXITM <OFFSET iname>

    ENDM

;=========================================================================
    .data
    .code
;=========================================================================
start:
;=========================================================================
    fn MessageBox,0,"fn","test",0
    fnc MessageBox,0,"\nfnc\n","test",0
    mov eax, rv(MessageBox,0,"rv","test",0)
    mov eax, rvc(MessageBox,0,"\nrvc\n","test",0)

    invoke MessageBoxW,0,uni$("uni$"),uni$("test"),0
    invoke MessageBoxW,0,_uni$("_uni$"),_uni$("test"),0

    inkey "Press any key to exit..."
    exit
;=========================================================================
end start


I didn't try to pin down exactly which statement in the fn, fnc, rv, and rvc macros is causing the problem, because it makes more sense to me to fix the problem in the uni$ macro.

BTW, I tested only ML 6.14 and 6.15.
eschew obfuscation

qWord

hi,
I've recognize this incompatibility also some time back: the problem is, that rv,fn,... declare a textmacro named 'arg' - when macros, like uni$, use this name it get replaced by something like 'invoke xyz...'.
IMO rv,fn,.. must be changed, because global reserving of the the name 'arg' is a waste.

macros.asm<>ucmacros.asm: constants name conflict

qWord
FPU in a trice: SmplMath
It's that simple!

MichaelW

#2
Quote from: qWord on February 02, 2011, 03:42:21 PM
I've recognize this incompatibility also some time back...

Thanks, I try to read every post but somehow I missed that one. It took me a considerable amount of time to track the problem down. If I change my test code to this:

    % echo *arg*
    fn MessageBox,0,"fn","test",0
    fnc MessageBox,0,"\nfnc\n","test",0
    mov eax, rv(MessageBox,0,"rv","test",0)
    mov eax, rvc(MessageBox,0,"\nrvc\n","test",0)
    % echo *arg*
    arg equ <>
    % echo *arg*


Then I get:

Assembling: test.asm
*arg*
*invoke MessageBoxA,0,OFFSET ??0049,OFFSET ??0050,0*
**
test.asm(132) : error A2065: expected : an identifier
uni$(51): Macro Called From
  test.asm(132): Main Line Code
test.asm(132) : fatal error A1008: unmatched macro nesting
uni$(68): Macro Called From
  test.asm(132): Main Line Code


So it looks to me like the uni$ and WSTR macros are dependent on some other macro having done an "arg equ ...", and all 6 of the macros involved need to be fixed, as a minimum.
eschew obfuscation

hutch--

It looks like renaming the "arg" needs to be done, probably in each macro with some non-reproducable mess like "arg@_@_1234" or similar.

LATER: Just renamed "arg" in all 4 macros and it appears to be working normally. I don't have a unicode test piece set up but it should solve any clash with the use of the word "arg".


  ; ----------------------------------------------------------------
  ; invoke enhancement. Add quoted text support to any procedure
  ; or API call by using this macro instead of the standard invoke.
  ; LIMITATION : quoted text must be plain text only, no ascii
  ; values or macro reserved characters IE <>!() etc ..
  ; use SADD() or chr$() for requirements of this type.
  ; ----------------------------------------------------------------
    fn MACRO FuncName:REQ,args:VARARG
      fn_@_arg equ <invoke FuncName>                ;; construct invoke and function name
      FOR var,<args>                                ;; loop through all arguments
        fn_@_arg CATSTR fn_@_arg,<,reparg(var)>     ;; replace quotes and append fn_@_arg
      ENDM
      fn_@_arg                                      ;; write the invoke macro
    ENDM

  ; ------------------------------------------------
  ; Function return value version of the above macro
  ; ------------------------------------------------
    rv MACRO FuncName:REQ,args:VARARG
      rv_@_arg equ <invoke FuncName>                ;; construct invoke and function name
      FOR var,<args>                                ;; loop through all arguments
        rv_@_arg CATSTR rv_@_arg,<,reparg(var)>     ;; replace quotes and append rv_@_arg
      ENDM
      rv_@_arg                                      ;; write the invoke macro
      EXITM <eax>                                   ;; EAX as the return value
    ENDM

  ; ---------------------------------------------------
  ; The two following versions support C style escapes.
  ; ---------------------------------------------------
    fnc MACRO FuncName:REQ,args:VARARG
      fnc_@_arg equ <invoke FuncName>               ;; construct invoke and function name
      FOR var,<args>                                ;; loop through all arguments
        fnc_@_arg CATSTR fnc_@_arg,<,cfm$(var)>     ;; replace quotes and append fnc_@_arg
      ENDM
      fnc_@_arg                                     ;; write the invoke macro
    ENDM

    rvc MACRO FuncName:REQ,args:VARARG
      rvc_@_arg equ <invoke FuncName>               ;; construct invoke and function name
      FOR var,<args>                                ;; loop through all arguments
        rvc_@_arg CATSTR rvc_@_arg,<,cfm$(var)>     ;; replace quotes and append rvc_@_arg
      ENDM
      rvc_@_arg                                     ;; write the invoke macro
      EXITM <eax>                                   ;; EAX as the return value
    ENDM
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php