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

# ctx.htm
Classes
CTX
CTX_FOR
CTX_MAC
Encodings
CtxEnc
Procedures
Ctx1stRepeat
CtxCreate
CtxDestroy
CtxDiscard
CtxExpansionNrUpdate
CtxFind
CtxForNext
CtxGetEndTypename
CtxPeek
CtxStatusAll

Object Ctx represents one program block . Whenever a block statement is executed, one Ctx object is pushed on Src.CtxStack and it is popped when the corresponding ENDblock is encounterred.

Proper block nesting must be maintained in noemitting state too.

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

       ctx HEAD ; Start of module interface.

↑ CTX
  Structure which describes block context. Context objects are kept on `Src.CtxStack`.

    CTX STRUC
    .NamePtr      D D ; Pointer to block identifier delocalized name.
    .NameSize     D D ; Size of block identifier.
    .ExpansionNr  D D ; Value of dynamic %variable %. which makes unique labels.
    .Status       D D ; Context boolean properties, see CtxEnc below.
                  ; +10h.
    .ObjPtr       D D ; Pointer to the corresponding object, depending on ctxAnyType, see CtxEnc below.
    .MacPtr       D D ; Pointer to MAC during macro definition.
    .PreviousSect D D ; ^SSS with section which was current before entering the block.
    .BlockSect    D D ; ^SSS with section of block-begin pseudoinstruction, possibly changed by AUTOSEGMENT=ON.
                  ; +20h.
    .LinePtr      D D ; Pointer to the 1st physical line of block-begin statement.
    .ChunkPtr     D D ; Pointer to CHUNK where .LinePtr belongs to.
    .LineNext     D D ; Pointer to the end of source line with macroinstruction invocation.
    .ChunkNext    D D ; Pointer to CHUNK where .LineNext belongs to.
                  ; +30h.
    .LineEnd      D D ; Pointer behind the 1st physical line of block-begin statement.
    .Shift        D D ; Ordinal operands number modifier. Default=0, increased by %SHIFT (%MACRO).
    .ValBuffer    D D ; ^BUFFER keeping values of operands in buffers below until the end of block expansion.
    .ObjBuffer    D D ; ^BUFFER which contains ^CTX_FOR or ^CTX_MAC object at block expansion.
                  ; +40h.
    .OrdBuffer    D D ; ^BUFFER of 2*DDs keeping values of ordinal operands at %MACRO/%FOR invocation.
    .KeyBuffer    D D ; ^BUFFER of 4*DDs keeping keyword operands at macro invocation.
    .FrmBuffer    D D ; ^BUFFER of 4*DD keeping ordinal and keyword formal parameters at %MACRO/%FOR invocation.
                      ; Their names are without %. In case of ctxFOR this buffer contains just one parameter.
      ENDSTRUC CTX

↑ CTX_MAC
  This structure describes some context properties of %MACRO expansion. In the context of expansion of block %MACRO..%ENDMACRO `CTX.ObjBuffer` contains an object of CTX_MAC structure. It is created at invocations of a macro.

    CTX_MAC STRUC
    .LabelPtr       D D ; Pointer to the label of macro invocation.
    .LabelSize      D D ; Size of the label of macro invocation.
    .MacroNamePtr   D D ; Pointer to the name of macro.
    .MacroNameSize  D D ; Size of the name of macro.
    .ProtoLinePtr   D D ; Pointer to the prototype (%MACRO statement).
    .InvokStmStatus D D ; STM.Status of the statement which invoked the macro.
        ENDSTRUC CTX_MAC

↑ CTX_FOR
  This structure describes some context properties of %FOR block expansion. In the context of expansion of block %FOR..%ENDFOR `CTX.ObjBuffer` contains an object of CTX_FOR structure.

    CTX_FOR STRUC
    .OrdinalNr    D D ; Curent ordinal number of processed %FOR operand.
    .NrOfOrdinals D D ; Maximal ordinal number of %FOR operands.
    .Step         D Q ; Current STEP value (signed integer). The value is -1 or +1 when flag CTX.Status:ctxStep0 is set.
    .Value        D Q ; Current formal variable numeric value. Also stored to CTX.FrmBuffer as a string.
    .RangeLeft    D Q ; Current operand range value. Ignored when the operand is not a range.
    .RangeRight   D Q ; Current operand range value. Ignored when the operand is not a range.
         ENDSTRUC CTX_FOR

↑ CtxEnc
  Encoding of context flags used in CTX.Status.

    ctxAnyType      = 0x0000_0FFF ; Block type mask. See also CtxGetEndTypename.CtxEndTypenameTable.
    ctxPROGRAM      = 0x0000_0001 ; CTX.ObjPtr=^PGM
    ctxPROC         = 0x0000_0002 ; CTX.ObjPtr=^SYM
    ctxPROC1        = 0x0000_0004 ; CTX.ObjPtr=^SYM
    ctxSTRUC        = 0x0000_0008 ; CTX.ObjPtr=^SSS
    ctxMACRO        = 0x0000_0010 ; CTX.ObjPtr=^CTX_MAC
    ctxFOR          = 0x0000_0020 ; CTX.ObjPtr=^CTX_FOR
    ctxWHILE        = 0x0000_0040 ; CTX.ObjPtr=0
    ctxREPEAT       = 0x0000_0080 ; CTX.ObjPtr=0
    ctxIF           = 0x0000_0100 ; CTX.ObjPtr=0
    ;               = 0x0000_0200 ; Unused.
    ctxHEAD         = 0x0000_0400 ; CTX.ObjPtr=0
    ctxCOMMENT      = 0x0000_0800 ; CTX.ObjPtr=0
                                  ; Other context properties.
    ctxDefinition   = 0x0000_1000 ; Block is being defined (STRUC, %MACRO).
    ctxExpansion    = 0x0000_2000 ; Block is being expanded (STRUC, %MACRO, %FOR, %WHILE, %REPEAT).
    ctxPrototype    = 0x0000_4000 ; %MACRO prototype is being prepared.
    ctxMacExpList   = 0x0000_8000 ; Macroinstruction entered when LIST=ON,LISTMACRO=ON,
     ; its expansion should be +listed even when the macro is defined in included file and LISTINCLUDE=OFF.
    ctxNamespace    = 0x0001_0000 ; This block defines namespace.
    ctxExpandable   = 0x0002_0000 ; Block has %. property (%FOR,%WHILE,%REPEAT,%MACRO).
    ctxFormal       = 0x0004_0000 ; Block has formal parameters (%FOR, %MACRO). All buffers reserved.
    ctxRepeat       = 0x0008_0000 ; This block is %FOR or %WHILE or %REPEAT (see LISTREPEAT).
    ctx1stRepeat    = 0x0010_0000 ; Repeat block is expanded for the 1st time. Display in listing.
    ctxNestingOff   = 0x0020_0000 ; This block was specified with key NESTINGCHECK=OFF.
    ctxIsRange      = 0x0040_0000 ; Current %FOR operand is numeric range.
    ctxStep0        = 0x0080_0000 ; Set if STEP=0 or if STEP= was not explicitly specified. Empiric slope will be used.
    ctxExited       = 0x0100_0000 ; %EXITblock encountered, ignore possible nesting errors.
    ctxElsed        = 0x0200_0000 ; %ELSE statement was already encountered in this ctxIF.
    ctxIfEmit       = 0x0400_0000 ; %IF block enterred in emitting status.
    ;               = 0x0800_0000 ; Unused.
    ctxPgmPassed    = 0x1000_0000 ; PGM has performed at least 1 pass. Used to skip PROGRAM stm in repeated passes.
    ctxPgmReturned  = 0x2000_0000 ; ENDPROGRAM just returned to its PROGRAM statement. Reset in PseudoPROGRAM.
    ctxMacLabeled   = 0x4000_0000 ; Macro definition has formal label %: declared in one of its statements.
    ctxNoEmit       = 0x8000_0000 ; Nonemitting part of block reached, such as false %IF, %COMMENT, EXITed etc.

      ENDHEAD ctx ; End of module interface.

    [.text]

↑ CtxPeek CtxType, CtxStackPtr
  CtxPeek will seek Src.CtxStack from below CtxStackPtr to bottom and returns the first context matching CtxType (or at least one of the flags if more than 1 specified).
  It does not change the context stack.
Input
  CtxType Flag in CTX.Status, e.g. ctxPROC.
  CtxStackPtr is pointer to the context (CTX structure) returned in previous CtxPeek invocation. It may be 0, top of context stack is used in this case.
Output
  CF=0 EAX= pointer to CTX structure.
Error
  CF=1 EAX=0 if no such context was found.
Invoked by
  ChunkSubHead Ctx1stRepeat IigRET MacFind MsgProc PgmCreateProgram PgmGetCurrent PgmoptSetDefaults PseudoENDPROGRAM PseudopcDROPMACRO PseudopcMACRO PseudopcSHIFT SrcAssemble StmListing StmParse SymDelocalName VarCheckFormal VarExpand

    CtxPeek Procedure CtxType, CtxStackPtr
          SUB EAX,EAX
          MOV [%ReturnEAX],EAX
          MOV EBX,[Src.CtxStack::]
          MOV EAX,[%CtxStackPtr]
          CMP EBX,1
          MOV EDX,[%CtxType]
          JC .99:
          TEST EAX
          JNZ .30:
          StackPeekLast EBX
    .10:  JC .99:
          TEST [EAX+CTX.Status],EDX
          JNZ .80:
    .30:  StackPeekPrev EBX,EAX
          JMP .10:
    .80:  MOV [%ReturnEAX],EAX
    .99: EndProcedure CtxPeek

↑ CtxGetEndTypename CtxType
  CtxGetEndTypename returns uppercase mnemonic of ENDblock specified with CtxType flag, such as "ENDPROC", "ENDSTRUC", "%ENDIF", "%ENDFOR" etc.
  It returns EXITblock mnemonic if CtxType.ctxExited is set.
Input
  CtxType Ctx.Status with flag identifying the context type.
Output
  EAX= pointer to DQ with name and size of ENDblock name. It points to a QWORD with pointer in low DD and size in high DD.
Error
  EAX= pointer to DQ 0,0 (empty name) when CtxType didn't specify a valid block.
Example
  CtxGetEndTypename ctxMACRO ; Returns string "%ENDMACRO".
Invoked by
  CtxDiscard SrcAssemble
Tested by
  t1210

    CtxGetEndTypename Procedure CtxType
         MOV EBX,[%CtxType]
         MOV ESI,.CtxEndTypenameTable:
         JNSt EBX,ctxExited,.10:
         MOV ESI,.CtxExitTypenameTable:
     .10:MOV EAX, .Dummy
         AND EBX,ctxAnyType
         BSF EDX,EBX                                 ; EDX=0 (ctxPROGRAM), 1(ctxPROC), 2(ctxPROC1)..11(ctxCOMMENT)
         JZ .80:
         CMP EDX,SIZE#.CtxEndTypenameTable /4
         JNB .80:
         MOV EAX,[ESI+4*EDX]
    .80: MOV [%ReturnEAX],EAX
         ; JMPS .90:
    [.data]
         ALIGN 4
    .Dummy DD 0,0
    .CtxEndTypenameTable DD \ ; The order must match CTX.Status:ctxAnyType.
         Dict_PseudoENDPROGRAM::,Dict_PseudoENDPROC::,    Dict_PseudoENDPROC1::,\
         Dict_PseudoENDSTRUC::,  Dict_PseudopcENDMACRO::, Dict_PseudopcENDFOR::,\
         Dict_PseudopcENDWHILE::,Dict_PseudopcENDREPEAT::,Dict_PseudopcENDIF::, \
         .Dummy,                 Dict_PseudoENDHEAD::,   Dict_PseudopcENDCOMMENT::
    .CtxExitTypenameTable DD \ ; The order must match CTX.Status:ctxAnyType.
         Dict_PseudoENDPROGRAM::,Dict_PseudoENDPROC::,    Dict_PseudoENDPROC1::,\
         Dict_PseudoENDSTRUC::,  Dict_PseudopcEXITMACRO::,Dict_PseudopcEXITFOR::,\
         Dict_PseudopcEXITWHILE::,Dict_PseudopcEXITREPEAT::,Dict_PseudopcELSE::, \
         .Dummy,                 Dict_PseudoENDHEAD::,   Dict_PseudopcENDCOMMENT::
         DS 0*CTX_MAC
    [.text]
    .90:EndProcedure CtxGetEndTypename

↑ CtxCreate CtxPtr, CtxStatus, StmPtr
  CtxCreate initializes context structure in block pseudoinstruction executing. It does not push the context on stack.
  Emitting and structure status is inherited from current status, other context flags should be provided via CtxStatus parameter.
  If CtxStatus:ctxExpandable&ctxExpansion is set, CtxCreate will increment and assign ExpansionNr and report E7140 when it exceeds MAXEXPANSIONS=.
  If CtxStatus:ctxFormal is set, CtxCreate will reserve all buffers necessarry for evaluation of formal %variables during block expansion.
Input
  CtxPtr Allocated fresh context object with undefined contents.
  CtxStatus Flags to set in CTX.Status.
  StmPtr Parsed block-begin statement.
Output
  .Name, .Status, .LinePtr, .ExpansionNr members of structure CTX are initialized, other members zeroed.
Error
  Errors are reported with macro Msg.
See also
Invokes
  EaBufferReserve SymDelocalName
Invoked by
  MacExpand PseudoData PseudoPROC PseudoPROC1 PseudoPROGRAM PseudoSTRUC PseudopcCOMMENT PseudopcFOR PseudopcIF PseudopcMACRO PseudopcREPEAT PseudopcWHILE
Tested by
  t1210

    CtxCreate Procedure CtxPtr, CtxStatus, StmPtr
          MOV EDI,[%CtxPtr]
          MOV EBX,[%StmPtr]
          Clear EDI,Size=SIZE#CTX
          Invoke EaBufferReserve::,CtxCreate
          MOV [EDI+CTX.ValBuffer],EAX                ; ValBuffer is always reserved, regardless of ctxExpandable.
          MOV EDX,[%CtxStatus]
         ; Set context name.
          MOV ECX,[EBX+STM.LabelSize]
          MOV ESI,[EBX+STM.LabelPtr]
          JNSt EDX,ctxMACRO,.20:
          JNSt EDX,ctxExpansion,.20:
          MOV ECX,[EBX+STM.OperationSize]            ; Macro invocation has context name in Stm.Operation instead of Stm.Label.
          MOV ESI,[EBX+STM.OperationPtr]
          JMP .30:
    .20:  JNSt EDX,ctxREPEAT, .30:
          ; %REPEAT statement is an exception: it has block name in its 1st ordinal instead of label field.
          BufferRetrieve [EBX+STM.OrdBuffer]
          JECXZ .50:
          MOV ECX,[ESI+4]
          MOV ESI,[ESI+0]
          StripColons ESI,ECX
    .30:  TEST ECX
          JNZ .40:
          JSt EDX,ctxIF|ctxRepeat|ctxCOMMENT|ctxHEAD, .50: ; Those blocks may have no name.
    .40:  Invoke SymDelocalName::,ESI,ECX,[EDI+CTX.ValBuffer],memberDelocal
          BufferRetrieve [EDI+CTX.ValBuffer]
          MOV [EDI+CTX.NamePtr],ESI                  ; Persistent delocalized block name.
          MOV [EDI+CTX.NameSize],ECX
    .50:  MOV EAX,[EBX+STM.LinePtr]
          MOV ECX,[EBX+STM.LineEnd]
          MOV ESI,[EBX+STM.ChunkPtr]
          MOV EBX,[EBX+STM.Section]
          MOV [EDI+CTX.LinePtr],EAX
          MOV [EDI+CTX.LineEnd],ECX
          MOV [EDI+CTX.ChunkPtr],ESI
          MOV [EDI+CTX.PreviousSect],EBX
          MOV [EDI+CTX.BlockSect],EBX
    .60:  JNSt EDX,ctxFormal,.80:
          Invoke EaBufferReserve::,CtxCreate
          MOV [EDI+CTX.ObjBuffer],EAX
          Invoke EaBufferReserve::,CtxCreate
          MOV [EDI+CTX.OrdBuffer],EAX
          Invoke EaBufferReserve::,CtxCreate
          MOV [EDI+CTX.KeyBuffer],EAX
          Invoke EaBufferReserve::,CtxCreate
          MOV [EDI+CTX.FrmBuffer],EAX
    .80:  MOV [EDI+CTX.Status],EDX
    .90: EndProcedure CtxCreate

↑ CtxDestroy CtxPtr
  CtxDestroy will release context buffers reserved in CtxCreate.
Input
  CtxPtr Pointer to CTX object.
Output
  Buffers released.
Error
  not detected.
See also
  CtxCreate
Invokes
  EaBufferRelease
Invoked by
  CtxDiscard

    CtxDestroy Procedure CtxPtr
          MOV EBX,[%CtxPtr]
          Invoke EaBufferRelease::,[EBX+CTX.ObjBuffer]
          Invoke EaBufferRelease::,[EBX+CTX.OrdBuffer]
          Invoke EaBufferRelease::,[EBX+CTX.KeyBuffer]
          Invoke EaBufferRelease::,[EBX+CTX.FrmBuffer]
          Invoke EaBufferRelease::,[EBX+CTX.ValBuffer]
         EndProcedure CtxDestroy

↑ CtxForNext CtxPtr
  CtxForNext assigns the first or the next value of formal variable.
Input
  CtxPtr is prepared %FOR context.
  Ctx.ObjBuffer contains CTX_FOR object, also pointed to with Ctx.ObjPtr.
  Ctx.OrdBuffer contains pairs of DD which are persistent copies of %FOR Stm.OrdBuffer, i.e. %FOR ordinal operands at block entry.
  Ctx.FrmBuffer contains 4*DD specifying formal name and its previous value. The value will be updated here.
Output
  CF=0 Formal variable in Ctx.FrmBuffer is assigned with the next value. `CTX_FOR.OrdinalNr` and `CTX_FOR.Value` will be updated, too.
  CF=1 at the end of expansion (all ordinals exhausted).
Error
  CF=1 Errors are reported with macro Msg.
See also
Invokes
  ExpEvalNum ExpParseRange
Invoked by
  PseudopcFOR
Tested by
  t2641

    CtxForNext Procedure CtxPtr
    RangeRightPtr  LocalVar
    RangeRightSize LocalVar
    CtxForNumber   LocalVar Size=20                  ; Room for the expanded number.
         MOV EBX,[%CtxPtr]
         MOV EDI,[EBX+CTX.ObjPtr]                    ; ^CTX_FOR
         JSt [EBX+CTX.Status],ctxIsRange,.60:
     .20:MOV EDX,[EDI+CTX_FOR.OrdinalNr]             ; Get the next ordinal.
         INC EDX
         CMP [EDI+CTX_FOR.NrOfOrdinals],EDX
         JC .99: ; No more ordinals.
         MOV [EDI+CTX_FOR.OrdinalNr],EDX
         BufferRetrieve [EBX+CTX.OrdBuffer]
         LEA ESI,[ESI+8*EDX-8]                       ; ESI now points to pair OrdValuePtr,OrdValueSize.
         MOV ECX,[ESI+4]
         MOV ESI,[ESI]
         LEA EDX,[ESI+ECX]
         Invoke ExpParseRange::,ESI,EDX
         JNC .30:                                    ; If the ordinal is numeric range.
         RstSt [EBX+CTX.Status],ctxIsRange
         MOV EDI,ESI
         MOV EDX,ECX
         BufferRetrieve [EBX+CTX.FrmBuffer]
         MOV [ESI+8],EDI                             ; Copy nonrange operand to formal variable value.
         MOV [ESI+12],EDX
         JMP .90:
     .30:SetSt [EBX+CTX.Status],ctxIsRange           ; %FOR loop has just enterred the next numeric range operand.
        ; ESI..EDX is range source notation, EAX points behind the range operator.
         SUB EDX,EAX
         MOV [%RangeRightPtr],EAX                    ; Save it for later evaluation.
         MOV [%RangeRightSize],EDX
         LEA ECX,[EAX-2]
         SUB ECX,ESI
         Invoke ExpEvalNum::,ESI,ECX                 ; RangeLeft evaluation.
         JC .20:                                     ; If syntax error, report Msg and go to the next operand.
         MOV [EDI+CTX_FOR.RangeLeft+0],EAX
         MOV [EDI+CTX_FOR.RangeLeft+4],EDX
         Invoke ExpEvalNum::,[%RangeRightPtr],[%RangeRightSize]
         JC .20:                                     ; If syntax error, report Msg and go to the next operand.
         MOV [EDI+CTX_FOR.RangeRight+0],EAX
         MOV [EDI+CTX_FOR.RangeRight+4],EDX
         JNSt [EBX+CTX.Status],ctxStep0,.40:
        ; If STEP=0, it will be actually +1 or -1.
         SUB ECX,ECX
         SUB EAX,[EDI+CTX_FOR.RangeLeft+0]
         SBB EDX,[EDI+CTX_FOR.RangeLeft+4]
         JS .35:                                     ; If range slope negative.
         MOV [EDI+CTX_FOR.Step+4],ECX
         INC ECX
         MOV [EDI+CTX_FOR.Step+0],ECX                ; Step:= +1.
         JMPS .40:
     .35:DEC ECX                                     ; Negative range slope.
         MOV [EDI+CTX_FOR.Step+0],ECX
         MOV [EDI+CTX_FOR.Step+4],ECX                ; Step:= -1.
     .40:JSt [EBX+CTX.Status],ctxStep0,.50:
         ; If nonzero range slope differs from the step sign, this operand will be skipped.
         MOV EAX,[EDI+CTX_FOR.RangeRight+0]
         MOV EDX,[EDI+CTX_FOR.RangeRight+4]
         SUB EAX,[EDI+CTX_FOR.RangeLeft+0]
         SBB EDX,[EDI+CTX_FOR.RangeLeft+4]
         JS .45:                                     ; If the range slope is negative.
         JNZ .43:                                    ; If the range slope is positive.
         TEST EAX
         JZ .50:                                     ; If the range slope is zero, e.g.  "1..1"
     .43:; Range slope is positive.
         TESTB [EDI+CTX_FOR.Step+7],0x80
         JNZ .20:                                    ; Ignore this range when the step is negative.
         JMPS .50:
     .45:TESTB [EDI+CTX_FOR.Step+7],0x80
         JZ .20:                                     ; If range slope is negative and step is positive, skip the operand.
     .50:MOV EAX,[EDI+CTX_FOR.RangeLeft+0]           ; Start with the left range value.
         MOV EDX,[EDI+CTX_FOR.RangeLeft+4]
         MOV [EDI+CTX_FOR.Value+0],EAX
         MOV [EDI+CTX_FOR.Value+4],EDX
         JMP .80:
     .60: ; %FOR processing is inside a numeric range.
         MOV EAX,[EDI+CTX_FOR.Value+0]
         MOV EDX,[EDI+CTX_FOR.Value+4]
         ADD EAX,[EDI+CTX_FOR.Step+0]
         ADC EDX,[EDI+CTX_FOR.Step+4]
         MOV [EDI+CTX_FOR.Value+0],EAX
         MOV [EDI+CTX_FOR.Value+4],EDX
         TESTB [EDI+CTX_FOR.Step+7],0x80
         JNZ .70:
         CMP EDX,[EDI+CTX_FOR.RangeRight+4]           ; Step is positive. EDX:EAX is the incremented formal value.
         JL .80:
         JG .20:                                      ; Out of range, continue with the next operand.
         CMP EAX,[EDI+CTX_FOR.RangeRight+0]
         JBE .80:
         JMP .20:                                     ; Out of range, continue with the next operand.
     .70:CMP EDX,[EDI+CTX_FOR.RangeRight+4]           ; Step is negative. EDX:EAX is the decremented formal value.
         JG .80:
         JL .20:                                      ; Out of range, continue with the next operand.
         CMP EAX,[EDI+CTX_FOR.RangeRight+0]
         JB .20:                                      ; Out of range, continue with the next operand.
     .80: ; Convert CTX_FOR.Value to decadic into CTX.KeyBuffer and update CTX.FrmBuffer.
         BufferClear [EBX+CTX.KeyBuffer]
         LEA ECX,[%CtxForNumber]
         MOV EAX,[EDI+CTX_FOR.Value+0]
         MOV EDX,[EDI+CTX_FOR.Value+4]
         StoQD ECX,Size=20,Signed=yes
         SUB EDI,ECX                                  ; Context.KeyBuffer will be misused to persistently keep the formal value.
         BufferStore [EBX+CTX.KeyBuffer],ECX,EDI
         BufferRetrieve [EBX+CTX.KeyBuffer]
         MOV EAX,ESI
         BufferRetrieve [EBX+CTX.FrmBuffer]
         MOV [ESI+8],EAX                              ; Pointer within KeyBuffer.
         MOV [ESI+12],EDI                             ; Number of digits in decadic value.
     .90:CLC
    .99:EndProcedure CtxForNext

↑ CtxExpansionNrUpdate CtxPtr, StmPtr
  CtxExpansionNrUpdate will load and increment Pass.ExpansionNr and copy it to Ctx.ExpansionNr. It will also report E7140 when ExpansionNr is greater than allowed MAXEXPANSIONS number, which may happen by programmer's mistake in endless loop.
Input
  CtxPtr Current expandable context.
  StmPtr Current parsed statement.
Output
  CF=0 ExpansionNr incremented in pass and context.
Error
  CF=1 MAXEXPANSIONS reached. ExpansionNr incremented, error E7140 reported by Msg.
Invoked by
  PseudopcFOR PseudopcMACRO PseudopcREPEAT PseudopcWHILE
Tested by
  t7362

    CtxExpansionNrUpdate Procedure CtxPtr, StmPtr
          MOV EBX,[%StmPtr]
          MOV EDI,[%CtxPtr]
          MOV ESI,[EBX+STM.Program]
          TEST ESI
          JZ .90:
          MOV ECX,[ESI+PGM.PassPtr]
          JECXZ .90:
          MOV EAX,[ECX+PASS.ExpansionNr]
          INC EAX
          MOV [ECX+PASS.ExpansionNr],EAX
          MOV [EDI+CTX.ExpansionNr],EAX
          LEA ESI,[ESI+PGM.Pgmopt]
          DEC EAX
          MOV ECX,[ESI+PGMOPT.MaxExpansions]
          CMP EAX,ECX
          CMC
          Msg cc=E,'7140',ECX                        ; Number of expansions exceeded MAXEXPANSIONS=!1D.
     .90:EndProcedure CtxExpansionNrUpdate

↑ Ctx1stRepeat
  Ctx1stRepeat inspect all contexts of ctxRepeat type, and returns `ctx1stRepeat` if all those underlying contexts have ctx1stRepeat set. Otherwise it returns `0`.
Input
  -
Output
  EAX=0 or ctx1stRepeat.
Error
  - not expected.
Invokes
  CtxPeek
Invoked by
  PseudopcFOR PseudopcREPEAT PseudopcWHILE
Tested by
  t2751

    Ctx1stRepeat Procedure
         SUB EAX,EAX
         MOV EDX,ctx1stRepeat
     .10:Invoke CtxPeek,ctxRepeat,EAX
         JC .90:
         JSt [EAX+CTX.Status],ctx1stRepeat,.10:
         XOR EDX,EDX
     .90:MOV [%ReturnEAX],EDX
         EndProcedure Ctx1stRepeat

↑ CtxStatusAll
  CtxStatusAll returns statuses from all contexts on stack, logically ORed.
Input
  -
Output
  EAX=Logical OR from all Ctx.statuses on CtxStack.
Error
  -
Invoked by
  StmParse VarExpand

    CtxStatusAll Procedure
         MOV EBX,[Src.CtxStack::]
         XOR ECX,ECX
         StackPeekLast EBX
         JC .90:
         OR ECX,[EAX+CTX.Status]
     .20:StackPeekPrev EBX,EAX
         JC .90:
         OR ECX,[EAX+CTX.Status]
         JMP .20:
     .90:MOV [%ReturnEAX],ECX
        EndProcedure CtxStatusAll

↑ CtxFind CtxType, StmPtr
  CtxFind searches context stack for the given CtxType with matching block identifier. The block identifier in statement is delocalized first, however, if given CtxType has ctxNamespace property, this context is not used for delocalization.
  If no matching blockId found, it returns the first context with matching CtxType.
  CtxFind does not change the context stack and does not report errors. It is invoked from ENDblock and EXITblock handlers.
Input
  CtxType One of Ctx.Status:ctxAnyType flag.
  StmPtr Pointer to a parsed STM currently processed (ENDblock or EXITblock). It may be 0, no block matching is performed in this case, returned ZF=0.
Output
  CF=0 EAX= pointer to CTX of requested type on the context stack.
  ZF=1 if block identifiers match.
  ZF=0 if CtxType found but block identifiers do not match.
Error
  CF=1 EAX=0 if no context of CtxType was on the stack.
Example
  Invoke CtxEnd, ctxFOR, EBX JC UnexpectedENDblock JZ UnmatchedENDblock
See also
  CtxDiscard.
Invokes
  EaBufferRelease EaBufferReserve SymDelocalName
Invoked by
  ChunkInclude PseudoENDPROC PseudoENDPROC1 PseudoENDPROGRAM PseudoENDSTRUC PseudoPROGRAM PseudopcELSE PseudopcENDCOMMENT PseudopcENDFOR PseudopcENDIF PseudopcENDMACRO PseudopcENDREPEAT PseudopcENDWHILE PseudopcEXITFOR PseudopcEXITMACRO PseudopcEXITREPEAT PseudopcEXITWHILE StmParseSET

    CtxFind Procedure CtxType, StmPtr
         MOVD [%ReturnEAX],0
         MOV EDX,[%CtxType]
         MOV EBX,[%StmPtr]
         StackPeekLast [Src.CtxStack::]
         JMPS .20:
     .10:StackPeekPrev [Src.CtxStack::],EDI
     .20:MOV CL,-1                                  ; Signalize that no matching blockId was found.
         JC .70:                                    ; If the context stack is empty.
         MOV EDI,EAX
         JNSt [EDI+CTX.Status],EDX,.10:
         CMPD [%ReturnEAX],0
         JNZ .30:
         MOV [%ReturnEAX],EDI                        ; Prepare to return the first context found for the case of not-matching blockId.
     .30:TEST EBX                                    ; EDI is context of desired type. If StmPtr provided, check blockId.
         JZ .80:                                     ; If blockId match cannot be tested, the 1st context will be used.
         MOV ESI,[EBX+STM.LabelPtr]
         MOV ECX,[EBX+STM.LabelSize]
         CMPD [EBX+STM.OperationData],PseudopcENDREPEAT::, IMM=DWORD
         JE .40:
         CMPD [EBX+STM.OperationData],PseudopcUNTIL::, IMM=DWORD
         JE .40:
         BufferRetrieve [EBX+STM.OrdBuffer]          ; Other than %ENDREPEAT have blockId in 1st ordinal.
         TEST ECX
         JZ .80:                                     ; Empty ENDblockId is always matching.
         MOV ECX,[ESI+4]
         MOV ESI,[ESI+0]
         StripColons ESI,ECX                         ; Get rid of trailing colon(s), if any.
     .40:TEST ECX                                    ; ESI,ECX is now the ENDblock identifier.
         JZ .80:                                     ; Empty ENDblockId is always matching.
         Invoke EaBufferReserve::,CtxFind
         Invoke SymDelocalName::,ESI,ECX,EAX,memberDelocalParent ; In case that block name has local scope.
         BufferRetrieve EAX
         Invoke EaBufferRelease::,EAX
     .50:Compare [EDI+CTX.NamePtr],[EDI+CTX.NameSize],ESI,ECX
         MOV CL,0                                    ; Mark matching blockId found.
         JE .80:                                     ; If blockId match, done. ZF=1.
         JMP .10:                                    ; Otherwise try to find a better context.
     .70:; Stack peeked but no matching blockId found.
         MOV EDI,[%ReturnEAX]
     .80:MOV [%ReturnEAX],EDI                        ; EDI=0 if no CtxType found. CL=0 if blockId match.
         TEST EDI
         STC
         JZ .90:                                     ; Return CF=ZF=1 if no such context is on stack.
         TEST CL                                     ; Return CF=0, ZF=1 if blockId match, otherwise CF=ZF=0.
     .90:EndProcedure CtxFind

↑ CtxDiscard CtxPtr, StmPtr
  CtxDiscard will pop the context pointed to with CtxPtr (and all above, if any) and, if not `Stm.CtxStatusAll:ctxExited`, report E7110 or E7120 on each block mismatch detected.
Input
  CtxPtr is pointer to CTX to be discarded (popped and destroyed). It must point to an existing context on stack.
  StmPtr is pointer to ENDblock parsed statement STM.
Output
  Specified context is removed from stack, block ends.
Error
  CF=1 Error E7110 is reported with macro Msg.
See also
  CtxFind.
Invokes
  CtxDestroy CtxGetEndTypename EaBufferRelease EaBufferReserve
Invoked by
  PseudoENDPROC PseudoENDPROC1 PseudoENDPROGRAM PseudoENDSTRUC PseudopcENDCOMMENT PseudopcENDFOR PseudopcENDIF PseudopcENDMACRO PseudopcENDREPEAT PseudopcENDWHILE
Tested by
  t1210

    CtxDiscard Procedure CtxPtr, StmPtr
    CtxDbuffer LocalVar                              ; Temporary buffer for contextes with NESTINGCHECK=OFF.
         Invoke EaBufferReserve::,CtxDiscard
         MOV [%CtxDbuffer],EAX
         MOV ESI,[%CtxPtr]
         MOV EBX,[%StmPtr]
         TEST ESI
         JZ .80:
         MOV EDX,[ESI+CTX.Status]
         AND EDX,ctxAnyType
     .10:StackPop [Src.CtxStack::]
         JC .60:
         MOV EDI,EAX
         CMP EDI,[%CtxPtr]
         JE .50:                                     ; If this is the context to discard.
         JSt [EBX+STM.CtxStatusAll],ctxExited,.50:   ; On EXITblock do not report mismatch.
         JNSt [EBX+STM.CtxStatusAll],ctxNestingOff,.20:
         ; If any context on stack has ctxNestingOff, do not report mismatch and
         ;   do not remove contexts above the one which is being discarded. Store them to CtxDbuffer instead.
         BufferStore [%CtxDbuffer],EDI,SIZE#CTX      ; Silently save it to be pushed back later in .70:.
         JMP .10:
     .20:JNSt [EBX+STM.CtxStatusAll],ctxRepeat,.30:
         JNSt [EBX+STM.CtxStatusAll],ctx1stRepeat,.50:
     .30:Invoke CtxGetEndTypename,[EDI+CTX.Status]
         JNSt [EDI+CTX.Status],ctxREPEAT,.40:
         XCHG EAX,EDI
     .40:Msg '7110',EAX,EDI                          ; Wrong nesting, expected "!1S !2S".',0
     .50:Invoke CtxDestroy,EDI
         CMP EDI,[%CtxPtr]
         JNE .10:
     .60:BufferRetrieve [%CtxDbuffer]                ; Zero or more undestroyed CTX objects.
     .70:LEA EDI,[ESI+ECX-SIZE#CTX]                  ; The last one.
         CMP EDI,ESI
         JB .80:                                     ; If no more saved contexts.
         StackPush [Src.CtxStack::],EDI              ; Return contexts back to stack in original order.
         SUB ECX,SIZE#CTX
         JMP .70:
     .80:Invoke EaBufferRelease::,[%CtxDbuffer]
     .90:EndProcedure CtxDiscard

       ENDPROGRAM ctx

▲Back to the top▲