EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

ctx.htm
Classes
CTX
CTX_FOR
CTX_MAC
Encodings
CtxEnc
Procedures
Ctx1stRepeat
CtxCreate
CtxDestroy
CtxDiscard
CtxExpansionNrUpdate
CtxFind
CtxForNext
CtxGetCurrent
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.


ctx PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
 EUROASM LISTINCLUDE=OFF
 INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
 EUROASM LISTINCLUDE=ON
   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.
.LinePtr      D D ; Pointer to the 1st physical line of block-begin statement.
.ChunkPtr     D D ; Pointer to CHUNK where .LinePtr belongs to.
              ; +20h.
.LineNext     D D ; Pointer to the end of source line with macroinstruction invocation.
.ChunkNext    D D ; Pointer to CHUNK where .LineNext belongs to.
.LineEnd      D D ; Pointer behind the 1st physical line of block-begin statement.
.PreviousSect D D ; ^SSS with section which was current before entering the block.
              ; +30h.
.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.
.OrdBuffer    D D ; ^BUFFER of 2*DDs keeping values of ordinal operands at %MACRO/%FOR invocation.
              ; +40h.
.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 .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 PseudopcDISPLAY 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::
[.text]
.90:EndProcedure CtxGetEndTypename
↑ CtxGetCurrent
CtxGetCurrent returns pointer to topmost CTX object on context stack.
Input
 
Output
CF=0
EAX= ^CTX
Error
CF=1 if context stack is empty.
EAX=0
See also
CtxPeek
Invoked by
PseudoENDPROGRAM PseudopcFOR PseudopcREPEAT PseudopcWHILE
CtxGetCurrent Procedure
      MOV EBX,[Src.CtxStack::]
      StackPeekLast EBX
      MOV [%ReturnEAX],EAX
     EndProcedure CtxGetCurrent
↑ 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:
  ; Macro invocation has context name in Stm.Operation instead of Stm.Label.
       MOV ECX,[EBX+STM.OperationSize]
       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],symDelocal
      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 [EDI+CTX.LinePtr],EAX
      MOV [EDI+CTX.LineEnd],ECX
      MOV [EDI+CTX.ChunkPtr],ESI
.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 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:
     ; Step is positive. EDX:EAX is incremented formal value.
     CMP EDX,[EDI+CTX_FOR.RangeRight+4]
     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:; Step is negative. EDX:EAX is decremented formal value.
     CMP EDX,[EDI+CTX_FOR.RangeRight+4]
     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
t8362
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
Tested by
t8349
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 ; Mark no matching blockId.
     JC .70: ; If empty stack.
     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: ; EDI is context of desired type. If StmPtr provided, check blockId.
     TEST EBX
     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
 .40:TEST ECX ; ESI,ECX is now ENDblock identifier.
     JZ .80: ; Empty ENDblockId is always matching.
     Invoke EaBufferReserve::,CtxFind
     Invoke SymDelocalName::,ESI,ECX,EAX,symDelocalParent
     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 if no such context on stack.
     TEST CL ; Return ZF if blockId match.
 .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]
     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▲