;===============================================================================
;
; MacroArgBegin
;
; Begin the parsing of a macro argument, by adding the file of the argument
; in the files list
;
; in a2 Point to "\xxx"
; a5 FILE*
;
; out a2 updated. Org a2 will point after the arg replaced
; updated a5
;
; destroy std + sp is modified
;
; TODO: when parsing args, strings are not escaped, but they should be
;
;===============================================================================
MacroArgBegin:
move.w MACRO_ARG_REF_COUNT(fp),d2 ; Counter (dbf) to find the FILE which contains the arg
addq.w #1,MACRO_ARG_REF_COUNT(fp) ; Update arg counter
cmp.w MACRO_REF_COUNT(fp),d2
beq ErrorInvalidOutOfMacro ; We are sure to avoid an underflow when browsing the files list
;----------------------------------------------------------------------
; Get the rank of the arg to replace
;----------------------------------------------------------------------
addq.l #1,a2 ; Skip \
movea.l a2,a0
bsr ReadIntBase10 ; Get #arg in d0
tst.b d1
bne ErrorInvalidMacroArg ; Overflow or NAN
move.l d0,d1 ; Save arg rank
movea.l a0,a2 ; Move the cursor after the macro arg
bsr SaveCursor ; Save current FILE state
;----------------------------------------------------------------------
; Get the file which contains the macro arguments
; This is the file which is before the Macro file
; It can be any previous file of the list
;----------------------------------------------------------------------
movea.l a5,a0
\Loop: cmpi.w #FILE.Type.Macro,FILE.Type(a0)
beq.s \Macro
addq.w #1,d2
\Macro: movea.l FILE.Parent(a0),a0
dbf.w d2,\Loop
;----------------------------------------------------------------------
; Add the file to the list and initialize it
;----------------------------------------------------------------------
movea.l (sp)+,a1 ; Save return value
lea -FILE.sizeof(sp),sp ; Create FILE
pea (a1) ; Restore return value
move.l sp,FILE.Child(a5) ; Save child in parent
move.l a5,FILE.Parent(sp) ; Save parent in child
movea.l sp,a5 ; Set new current FILE
move.w FILE.Handle(a0),FILE.Handle(a5) ; Create a copy of the file which contains the macro args
move.w FILE.CursorOffset(a0),FILE.CursorOffset(a5)
move.w FILE.NumLine(a0),FILE.NumLine(a5)
move.w #FILE.Type.MacroArg,FILE.Type(a5)
clr.l FILE.Child(a5)
;----------------------------------------------------------------------
; Special case: \0
;----------------------------------------------------------------------
bsr RestoreCursor
tst.w d1
bne.s \Not0
cmpi.b #'.',(a2)+
bne ErrorInvalidMacroArg
bra.s \End ; Size could be another macro argument
;----------------------------------------------------------------------
; If the macro call has a size, a2 points to the dot. Then we can find another macro arg (\xxx) or a size
; If there is not size, a2 point to the first char after the macro: we have just to skip blanks
;----------------------------------------------------------------------
\Not0: movea.l a2,a0
cmpi.b #'.',(a0)+
bne.s \SkipSpaces
;----------------------------------------------------------------------
; We must skip a macro arg or a size
;----------------------------------------------------------------------
cmpi.b #'\',(a0)+
bne.s \SkipSpaces ; This is a size, we know that it is valid, skip it then skip spaces
bsr ReadIntBase10 ; We know that this int is valid, just skip it
\SkipSpaces:
jsr SKIP_SPACES(fp)
movea.l a0,a2
;----------------------------------------------------------------------
; Find the right argument
; To get the next argument, we skip chars until a comma, but some chars are forbidden
;----------------------------------------------------------------------
\SkipArgLoop:
subq.w #1,d1
beq.s \End
\NextChar:
move.b (a2)+,d0
beq ErrorInvalidMacroArg
IF_D0 ',',\SkipArgLoop ; Args are separated with a comma
IF_D0 EOL,ErrorInvalidMacroArg
IF_D0 HTAB,ErrorInvalidMacroArg
IF_D0 SPACE,ErrorInvalidMacroArg
IF_D0 ASM_COMMENT_CHAR,ErrorInvalidMacroArg
IF_D0 '"',\SkipString
IF_D0 DOUBLE_QUOTE,\SkipString
bra.s \NextChar
\SkipString:
lea -1(a2),a0 ; Point to the simple or double quote
bsr SkipString
move.l a0,d0
beq ErrorInvalidMacroArg
movea.l a0,a2
bra.s \NextChar
\End: cmpi.b #'\',(a2)
beq MacroArgBegin ; Replacement data is also a macro argument, so start again the procedure
rts
;===============================================================================
;
; MacroArgEnd
;
; Called when the parsing of a macro argument is terminated
; Can be called even if we are not parsing a macro argument
; Remove all levels of recursion
;
; in nothing
;
; out updated a5 and a2
;
; destroy a0. sp is modified
;
;===============================================================================
MacroArgEnd:
movea.l (sp)+,a0
\Loop: tst.w MACRO_ARG_REF_COUNT(fp)
beq.s \End
subq.w #1,MACRO_ARG_REF_COUNT(fp)
movea.l FILE.Parent(a5),a5 ; Drop current FILE
lea FILE.sizeof(sp),sp
bra.s \Loop
\End pea (a0)
bra RestoreCursor