| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# mac.htm
Class
MAC
Encodings
MacEnc
Procedures
MacCtxUpdate
MaxExpand
MacFind
MacListMerge
MacPrototype

Object MAC represents one macroinstruction.
Mac objects (macro definitions) are kept on PASS.MacList.
MacList is empty in the beginning of each pass.
Macros defined in program pass are merged with parent program's macros when the last pass terminates. Scope of macros and %variables begins with their definition and ends at the end of source.

When a macro is invoked (expanded), its arguments are stored to context, and assembly is redirected to the macro prototype (%MACRO statement of invoked macro). Assembly returns below the macro invocation when the coresponding %ENDMACRO has been assembled.

Macro expansion object model
  `SampleMacro %MACRO Ord1,Ord2,Ord3,Key1=Key1Val,Key2=Key2Val` ; Macro prototype statement. `; Body of SampleMacro goes here.` `%ENDMACRO SampleMacro` Macro definition above is parsed and ignored in ctxDefinition, reference to prototype is saved to PASS.Maclist. `SampleLabel: SampleMacro Ord1Val,Ord2Val,,,Ord5Val,Key2=NewKey2Val,Key3=NewKey3Val` Macro invocation above is parsed, assembly context is redirected to the line where was the SampleMacro defined. Prototype in ctxExpansion is parsed to Stm by StmParse: Stm.OrdBuffer: Ord1,Ord2,Ord3 Stm.KeyBuffer: Key1=Key1Val,Key2=Key2Val Parsed macro invocation is stored to the context object by MacExpand >MacCtxUpdate: Ctx.ObjBuffer: SampleLabel,SampleMacro Ctx.OrdBuffer: Ord1Val,Ord2Val,,,Ord5Val Ctx.KeyBuffer: Key2=NewKey2Val,Key3=NewKey3Val ; Warn undeclared keyword Key3= MacPrototype merges operands of invokation with operands of prototype: Ctx.FrmBuffer: Ord1=Ord1Val,Ord2=Ord2Val,Ord3=,=,=Ord5Val,Key1=Val1,Key2=NewKey2Val Values of automatic macro variables will be %set on demand in VarExpand as if the following statements were virtually performed: %: %SET SampleLabel ; Label actually used at invocation. %* %SET Ord1Val,Ord2Val,,,Ord5Val ; Ordinals actually used at invocation. %# %SETA 5 ; Five ordinals actually used at invocation, though two of them are empty. %=* %SET Key2=NewKey2Val,Key3=NewKey3Val %=# %SETA 2 ; Two keywords are actually used at invocation, though Key3= is undeclared and ignored. %0 %SET SampleMacro ; 0th operand is the macro name. %1 %SET Ord1Val ; The value used on macro invocation as 1st operand. %3 %SET ; Empty, as no 3rd operand was used on macro invocation. %5 %SET Ord5Val ; 5th operand used on macro invocation (though it was not explicitly declared in protoype). %Key1 %SET Key1Val ; As Key1 wasn't mentioned in macro invocation, default from prototype is used. %Key2 %SET NewKey2Val ; Default from prototype is rewritten with new value specified in macro invocation. %Key3 %SET ; Empty because this keyword was not declared in prototype. When %ENDMACRO is encountered in ctxExpansion, assembly returns back just below the macro invokation statement and ctxMACRO+ctxExpansion is discarded.

    mac PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
        INCLUDEHEAD euroasm.htm, \  Interface (structures, symbols and macros) of other modules used in this source.
         ctx.htm,ea.htm,eaopt.htm,exp.htm,msg.htm,pass.htm,pgm.htm,pgmopt.htm,stm.htm

      mac HEAD ; Start of module interface.

↑ MAC
  Object of this class represents a defined macro.

    MAC STRUC
    .NamePtr  D D ; Pointer to macro name.
    .NameSize D D ; Size of macro name.
    .LinePtr  D D ; Pointer to the first physical line of %MACRO statement (definition of the macro) or 0 when the macro was dropped.
    .Status   D D ; Macro properties.
      ENDSTRUC MAC

↑ MacEnc
  Encoding of flags used in MAC.Status.

    macLabeled  = 0x00000001 ; Formal label %: occured at least once in some statement of macro definition.

      ENDHEAD mac ; End of module interface.

↑ MacExpand Stm
  MaxExpand is statement handler for macroinstructions. Name of the macro is in `Stm.OperationPtr/Size`.
  `Stm.OperationData` contains pointer to MAC object and MAC.LinePtr points to the corresponding %MACRO statement with macro definition.
  MacExpand creates context ctxMACRO+ctxExpansion.
Input
  Stm is pointer to the parsed STM statement.
Output
  Context stack modified, prototype prepared.
Error
  CF=1 Errors are reported with macro Msg.
Invokes
  CtxCreate MacCtxUpdate StmCheckFields
Invoked by
  StmExecute

    [.text]
    MacExpand Procedure Stm
         MOV EBX,[%Stm]
         Invoke StmCheckFields::,EBX,"*0**"
         StackPush [Src.CtxStack::],0
         LEA ECX,[EBX+STM.OperationPtr]
         Msg cc=C,'9312',ECX ; Allocation error expanding macro !1S.
         MOV ECX,ctxMACRO+ctxExpansion+ctxExpandable+ctxFormal+ctxPrototype
         ; Examine listing status.
         JNSt [Ea.Eaopt.Status::],eaoptLIST,.50:
         JNSt [Ea.Eaopt.Status::],eaoptLISTMACRO,.50:
         ; Indicate that macroexpansion should be +listed
         ; even when the macro is defined in included file and LISTINCLUDE=OFF:
         SetSt ECX,ctxMacExpList
     .50:Invoke CtxCreate::,EAX,ECX,EBX
         Invoke MacCtxUpdate,EAX,EBX       ; Copy macro operands to context buffers.
         MOV ECX,[EBX+STM.OperationData]   ; Pointer to MAC object with macro declaration.
         MOV EAX,[ECX+MAC.LinePtr]
         MOV [EBX+STM.LineNext],EAX        ; Continue assembly with macro prototype statement.
         MOVD [EBX+STM.ChunkNext],0
     .90:EndProcedure MacExpand

↑ MacCtxUpdate CtxPtr, StmPtr
  Procedure MacCtxUpdate will copy macroinstruction operands from parsed statement (where they have limited lifetime) to buffers from CTX object in order to persistently store operand names and values until the macro is completely expanded and %MACRO..%ENDMACRO block abandoned.
Input
  CtxPtr Pointer to CTX already created with CtxCreate.
  StmPtr Pointer to the parsed statement with macroinstruction.
Output
  Context is updated, CTX.OrdBuffer and CTX.KeyBuffer filled, CTX.ValBuffer is used as persistent storage. CTX.FrmBuffer is reserved but empty.
Error
  CF=1 Errors are reported with macro Msg.
See also
  MacPrototype.
Invoked by
  MacExpand
Tested by
  t7215

    MacCtxUpdate Procedure CtxPtr, StmPtr
    McuPassPool LocalVar ; Current program pass pool.
         MOV EBX,[%StmPtr]
         MOV EDX,[%CtxPtr]
         MOV EAX,[EBX+STM.Program]
         MOV ECX,[EAX+PGM.PassPtr]
         TEST ECX
         JNZ .05:
    .F9312:LEA ECX,[EBX+STM.OperationPtr]
         Msg '9312',ECX ; Allocation error expanding macro !1S.
         STC
         JMP .90:
    .05: MOV EAX,[ECX+PASS.Pool]
         TEST EAX
         MsgUnexpected cc=Z
         MOV [%McuPassPool],EAX
         MOV EAX,[EBX+STM.LineEnd] ; LinePtr to the statement which follows macro invocation.
         MOV EDI,[EBX+STM.ChunkPtr]
         SUB ECX,ECX
         MOV [EDX+CTX.LineNext],EAX ; Where to continue when the expansion is over.
         MOV [EDX+CTX.ChunkNext],EDI
         MOV [EDX+CTX.Shift],ECX
         ; Update context with MacPtr from statement and copy flag MAC.Status:macLabeled to CTX.Status:ctxMacLabeled
         ; in order to to indicate whether %: should be expanded implicitly.
         MOV ESI,[EBX+STM.OperationData] ; In case of macroinstruction it is ^MAC.
         MOV [EDX+CTX.MacPtr],ESI
         JNSt [ESI+MAC.Status],macLabeled,.10:
         SetSt [EDX+CTX.Status],ctxMacLabeled
    .10: BufferRetrieve [EBX+STM.OrdBuffer] ; Copy ordinal operands from invocation to context.OrdBuffer.
         ; ESI,ECX is QWORDs (Ptr,Size) for each ordinal used in macro invocation. ECX is 0,8,16,24,...
         ; However their lifetime is limited to StmFlush.
         BufferStore [EDX+CTX.OrdBuffer],ESI,ECX
         JC .F9312:
         BufferRetrieve [EDX+CTX.OrdBuffer]
         ; Ordinal lifetime will be prolonged to the end of macroexpansion.
         JECXZ .30: ; All ordinals copied.
    .20: PoolStore [%McuPassPool],[ESI+0],[ESI+4] ; Make the ordinal value persistent till end of pass.
         JC .F9312:
         MOV [ESI+0],EAX
         ADD ESI,8
         SUB ECX,8
         JA .20: ; Next ordinal.
    .30: BufferRetrieve [EBX+STM.KeyBuffer] ; Copy keyword operands from invocation to context.KeyBuffer.
         BufferStore [EDX+CTX.KeyBuffer],ESI,ECX
         JC .F9312:
         BufferRetrieve [EDX+CTX.KeyBuffer]
         ; ESI,ECX is four DWORDs (NamePtr,NameSize,ValPtr,ValSize) for each keyword used in macro invocation.
         ; Keywords will be made persistent to the end of expansion.
         JECXZ .50: ; All keywords copied.  ECX was 0,16,32,...
    .40: PoolStore [%McuPassPool],[ESI+0],[ESI+4] ; Make the keyword name persistent.
         JC .F9312:
         MOV [ESI+0],EAX
         PoolStore [%McuPassPool],[ESI+8],[ESI+12] ; Make the keyword value persistent.
         JC .F9312:
         MOV [ESI+8],EAX
         ADD ESI,16
         SUB ECX,16
         JG .40: ; Next keyword.
    .50: BufferNew [EDX+CTX.ObjBuffer],SIZE# CTX_MAC
         JC .F9312:
         MOV EDI,EAX ; ^CTX_MAC in CTX.ObjBuffer.
         MOV ESI,[EBX+STM.LabelPtr]
         MOV ECX,[EBX+STM.LabelSize]
         PoolStore [%McuPassPool],ESI,ECX
         JC .F9312:
     ; Copy misc info from invocation to context.ObjBuffer in the format CTX_MAC.
         MOV [EDI+CTX_MAC.LabelPtr],EAX   ; Label of macro invokation.
         MOV [EDI+CTX_MAC.LabelSize],ECX
         MOV ESI,[EBX+STM.OperationPtr]
         MOV ECX,[EBX+STM.OperationSize]
         PoolStore [%McuPassPool],ESI,ECX ; Make macroname persistent (it may be used to expand %0).
         JC .F9312:
         MOV [EDI+CTX_MAC.MacroNamePtr],EAX
         MOV [EDI+CTX_MAC.MacroNameSize],ECX
         MOV EAX,[EBX+STM.OperationData]
         MOV [EDI+CTX_MAC.ProtoLinePtr],EAX ; LinePtr to %MACRO prototype in source.
         MOV EAX,[EBX+STM.Status]
         MOV [EDI+CTX_MAC.InvokStmStatus],EAX ; STM.Status of macro invocation.
    .90:EndProcedure MacCtxUpdate

↑ MacPrototype CtxPtr, StmPtr
  MacPrototype will merge operands of macroinstruction invocation with operands of %MACRO prototype and prepare formal %variables in CTX.FrmBuffer.
Input
  CtxPtr Ptr to CTX which was pushed on invocation of the macro with its actual operands in ObjBuffer,OrdBuffer,KeyBuffer.
  StmPtr Ptr to parsed STM with prototype %MACRO statement which yields the default keyword values and formal names of all operands in its .OrdBuffer and .KeyBuffer.
Output
  FrmBuffer in CTX object will be updated with actual operands. They will be used later to dynamically construct special macro %variables (%*,%#,%1 etc).
Error
  Errors are reported with macro Msg.
See also
  MacCtxUpdate.
Invoked by
  PseudopcMACRO

    MacPrototype Procedure CtxPtr, StmPtr
    MpPassPool LocalVar
    FrmVar     LocalVar Size=16 ; VarNamePtr,VarNameSize,VarValuePtr,VarValueSize
    FrmMax     LocalVar ; Greater of ordinals length in STM.OrdBuffer and CTX.OrdBuffer. 0,8,16,,,
    FrmNdx     LocalVar ; 0,8,16,...FrmMax-8
         MOV EBX,[%StmPtr] ; Statement with %MACRO (prototype).
         MOV EDX,[%CtxPtr] ; Context with invocation operands.
         MOV EAX,[EBX+STM.Program]
         MOV ECX,[EAX+PGM.PassPtr]
         TEST ECX
         JZ .F9312:
         MOV EAX,[ECX+PASS.Pool]
         TEST EAX
         JZ .F9312:
         MOV [%MpPassPool],EAX
         ; Merge ordinal operands.
         BufferRetrieve [EBX+STM.OrdBuffer]
         MOV [%FrmMax],ECX
         BufferRetrieve [EDX+CTX.OrdBuffer]
         CMP ECX,[%FrmMax]
         JBE .10:
         MOV [%FrmMax],ECX
     .10:SUB ECX,ECX
         MOV [%FrmNdx],ECX ; Start with the 1st ordinal.
     .20:LEA EDI,[%FrmVar] ; Loop .20: .. .50: ordinal operands.
         SUB EAX,EAX
         MOV ECX,4
         REP STOSD ; Clear FrmVar.
         MOV EDI,[%FrmNdx]
         CMP EDI,[%FrmMax]
         JNB .50:
         BufferRetrieve [EBX+STM.OrdBuffer]
         CMP EDI,ECX
         JNB .30:
         ; Make ordinal name persistent to the end of macro expansion.
         MOV ECX,[EDI+ESI+4]
         MOV ESI,[EDI+ESI+0]
         PoolStore [%MpPassPool],ESI,ECX
         JC .F9312:
         MOV [%FrmVar+0],EAX ; Persistent ordinal name ptr.
         MOV [%FrmVar+4],ECX ; Ordinal name size (may be 0 when the ordinal is unnamed).
     .30:BufferRetrieve [EDX+CTX.OrdBuffer]
         CMP EDI,ECX
         JNB .40:
         MOV ECX,[EDI+ESI+4] ; Ordinal value size.
         MOV ESI,[EDI+ESI+0] ; ValuePtr. It's already been made persistent in MacCtxUpdate.
         MOV [%FrmVar+8],ESI
         MOV [%FrmVar+12],ECX
     .40:LEA ESI,[%FrmVar]
         BufferStore [EDX+CTX.FrmBuffer],ESI,16
         JC .F9312:
         ADDD [%FrmNdx],8
         JMP .20:
     .50:; Merge keyword operands. First store keywords from prototype with their default values.
         BufferRetrieve [EBX+STM.KeyBuffer]
         TEST ECX
         JZ .60:
     .52:PUSH ECX ; Loop .52: .. .60: keyword operands.
          MOV EDI,[ESI+0] ; NamePtr.
          MOV ECX,[ESI+4] ; NameSize.
          PoolStore [%MpPassPool],EDI,ECX
          JC .F9312:
          MOV [%FrmVar+0],EAX ; Persistent ordinal name ptr.
          MOV [%FrmVar+4],ECX ; Ordinal name size.
          MOV EDI,[ESI+8] ; ValuePtr.
          MOV ECX,[ESI+12] ; ValueSize.
          PoolStore [%MpPassPool],EDI,ECX
          MOV [%FrmVar+8],EAX ; Persistent default value ptr.
          MOV [%FrmVar+12],ECX ; Persistent default value size.
          LEA EDI,[%FrmVar]
          BufferStore [EDX+CTX.FrmBuffer],EDI,16 ; Save keyword with default value.
         POP ECX
         JNC .55:
    .F9312:Msg '9312',EBX ; Allocation error expanding macro !1S.
         STC
         JMP .90:
     .55:ADD ESI,16
         SUB ECX,16
         JG .52:
     .60: ; Each keyword in macro invocation should be found in CTX.FrmBuffer, otherwise W2610,
          ; and its value will update the stored key.
         BufferRetrieve [EDX+CTX.KeyBuffer]
         JECXZ .90:
     .62:PUSH ECX,ESI
           MOV EDI,[ESI+0] ; Name ptr.
           MOV EAX,[ESI+4] ; Name size.
           ; Search for keyword EDI,EAX in CTX.FrmBuffer.
           BufferRetrieve [EDX+CTX.FrmBuffer]
           JECXZ .W2610: ; If keyword not found.
     .70:  Compare [ESI+0],[ESI+4],EDI,EAX
           JE .75: ; If keyword found.
           ADD ESI,16
           SUB ECX,16
           JG .70:
    .W2610:MOV EAX,[ESP] ; ^QWORD keyword from CTX.KeyBuffer.
           Msg '2610',EAX,[EBX+STM.LinePtr]; Parameter "!1S=" was not specified in macro prototype at !2@. Ignored.
           JMPS .80:
     .75:  ; Matching keyword in CTX.FrmBuffer is addressed with ESI,
           ; its default value will be overwritten with value from CTX.KeyBuffer.
           MOV EDI,[ESP] ; ^QWORD keyword from CTX.KeyBuffer.
           MOV EAX,[EDI+8] ; Persistent new key value ptr.
           MOV ECX,[EDI+12] ; New key value size.
           MOV [ESI+8],EAX
           MOV [ESI+12],ECX
     .80:POP ESI,ECX
         ADD ESI,16
         SUB ECX,16
         JG .62:
    .90:EndProcedure MacPrototype

↑ MacFind NamePtr, NameSize
  MacFind searches for macro with given name on Pass.MacList belonging to all PROGRAMs on context stack, beginning with the last program. The search is case sensitive.
  If the macro name is found on MacList but its MAC.LinePtr is NULL, which happens in %DROPMACRO, searching stops and does not continue with parent PROGRAMs.
Input
  NamePtr Pointer to macro name.
  NameSize Size of macro name.
Output
  CF=0 EAX= pointer to MAC structure which contains macro name and LinePtr to the %MACRO definition statement.
Error
  CF=1 EAX=0 Macro was not found.
  CF=1 EAX= ^MAC with this name, which was dropped.
Invokes
  CtxPeek
Invoked by
  PseudopcDROPMACRO PseudopcMACRO StmParse
Tested by
  t7232

    MacFind Procedure NamePtr, NameSize
           SUB EDI,EDI
           MOV [%ReturnEAX],EDI
     .10:  Invoke CtxPeek::,ctxPROGRAM,EDI
           JC .90:
           MOV EDI,EAX
           MOV EBX,[EAX+CTX.ObjPtr]
           TEST EBX
           JZ .10:
           MOV ECX,[EBX+PGM.PassPtr]
           JECXZ .10:
           MOV EDX,[ECX+PASS.MacList]
           ListGetLast EDX
     .50:  JZ .10:
           Compare [%NamePtr],[%NameSize],[EAX+MAC.NamePtr],[EAX+MAC.NameSize]
           JE .70:
           ListGetPrev EAX
           JMP .50:
     .70: MOV ECX,[EAX+MAC.LinePtr]
          STC
          JECXZ .90: ; Zero LinePtr signalizes that the macro was dropped.
          CLC
          MOV [%ReturnEAX],EAX
     .90:EndProcedure MacFind

↑ MacListMerge ParentPass, ChildPass
  MacListMerge copies macro names defined during ChildProgram.Pass to ParentProgram.Pass.MacList.
  Names must be reallocated on ParentProgram.Pass.Pool because the ChildPass is about to end.
Input
  ParentPass Pointer to PASS to whose .MacList the macros will be copied to.
  ChildPass Pointer to PASS whose .MacList contains source macro names defined in this pass, including dropped macros.
Output
  Macro names are copied.
Errors
  not detected.
See also
  VarListMerge.
Invoked by
  PseudoENDPROGRAM

    MacListMerge Procedure ParentPass, ChildPass
         MOV EBX,[%ParentPass]
         MOV EDX,[%ChildPass]
         ListGetFirst [EDX+PASS.MacList]
         JZ .90:
     .10 MOV ESI,EAX ; Ptr to MAC.
         PoolStore [EBX+PASS.Pool],[ESI+MAC.NamePtr],[ESI+MAC.NameSize]
         MOV [ESI+MAC.NamePtr],EAX ; Reallocated ptr to name.
         ListStore [EBX+PASS.MacList],ESI
         ListGetNext ESI
         JNZ .10:
     .90:EndProcedure MacListMerge

      ENDPROGRAM mac

▲Back to the top▲