struct TListingLine
  .ptrLine  dd ?        ; pointer to the formated line text.
  .Nesting  dd ?        ; nesting level. The color of the background of listing browser.
                        ; will depend on this in order to indicate different files.
  .ptrFile  dd ?        ; filename where generated or NULL if generated by macro.
  .LineNum  dd ?        ; line number inside the file or pointer to TListingLine if generated by macro.
ends



; Creates listing from the given FAS file.
; Puts the listing in the memory stream. ptrVarStream is a pointer to the variable containing pointer to the stream.
; Pointer to every line is placed in the array. ptrVarArray is pointer to the variable that points to the array of dwords.


proc CreateListing, .ptrVarStream, .ptrVarArray, .ptrFAS, .ptrPreprocessed
.asmlen dd ?
begin
        pushad

        stdcall CreateMemoryStream, [.ptrVarStream], $1000
        stdcall CreateArray, 4
        mov     ecx, [.ptrVarArray]
        mov     [ecx], eax

        mov     ebx, [.ptrFAS]
        mov     esi, [ebx+TDumpHeader.ofsAsmDump]
        add     esi, ebx                                ; esi - pointer to the assembler dump section of FAS file.

        mov     eax, [ebx+TDumpHeader.lenAsmDump]
        mov     [.asmlen], eax

.linesloop:
        cmp     [.asmlen], 4
        jbe     .endofdump

.notlast:
        cmp     [esi+TAsmDumpElement.extSIB+sizeof.TAsmDumpElement], 0
        jne     .nextline

        cmp     [esi+TAsmDumpElement.flagVirtual+sizeof.TAsmDumpElement], 0
        jne     .nextline

        mov     eax, dword [esi+TAsmDumpElement.ofsBinary]
        cmp     eax, dword [esi+TAsmDumpElement.ofsBinary+sizeof.TAsmDumpElement]
        je      .nextline

.thisline:
        inc     [AsmLines]

        mov     ebx, [esi+TAsmDumpElement.ofsPreprocessed]
        add     ebx, [ptrPreprocessed]

; process one line, pointed by ebx
        stdcall CreateLineString, ebx
        push    eax

.findbaseline:
        test    byte [ebx+TIntLine.LineNumber+3], $80
        jz      .lineok

        mov     eax, [ebx+TIntLine.ofsGenerator]
        add     eax, [ptrPreprocessed]
        cmp     word [eax+1], '__'      ; is it internal macro definition?
        je      .searchdown

        mov     ebx, [ebx+TIntLine.ofsSourceLine] ; get the line where the macro was invoked.
        add     ebx, [ptrPreprocessed]
        jmp     .findbaseline

.searchdown:
        mov     ebx, [ebx+TIntLine.ofsMacroLine]
        add     ebx, [ptrPreprocessed]
        test    byte [ebx+TIntLine.LineNumber+3], $80
        jnz     .searchdown

.lineok:
        mov     edi, eax

        pop     [edi+TDebugLine.strLine]

        mov     eax, dword [esi+TAsmDumpElement.Address]
        mov     edx, dword [esi+TAsmDumpElement.Address+4]
        mov     dword [edi+TDebugLine.Address], eax
        mov     dword [edi+TDebugLine.Address+4], edx

        mov     ecx, dword [ebx+TIntLine.LineNumber] ; line number.
        mov     [edi+TDebugLine.LineNum], ecx

        mov     eax, [iLastFilename]
        mov     ecx, [ebx+TIntLine.ofsGenerator]

        test    ecx, ecx
        jnz     .notmain

        mov     ecx, [input_file]
        sub     ecx, [ptrPreprocessed]

.notmain:
        add     ecx, [ptrPreprocessed]
        cmp     [ptrLastFilename], ecx
        je      .filenameok

        mov     [ptrLastFilename], ecx
        stdcall FileNameSearchAdd, ecx       ; filename, returns index in the filename array.
        mov     [iLastFilename], eax

.filenameok:
        mov     [edi+TDebugLine.iFile], eax

.nextline:
        add     esi, sizeof.TAsmDumpElement
        sub     [.asmlen], sizeof.TAsmDumpElement
        jmp     .linesloop

.endofdump:
        popad
        return
endp



proc FormatListingLine, .ptrVarStream, .ptrLine

.x    dd ?
.char dd ?

begin
        push    esi edi ebx

        stdcall GetStreamRoom, [.ptrVarStream], $1000
        push    edi                             ; this will be returned.
        add     edi, ebx

        mov     esi, [.ptrLine]
        lea     esi, [esi+TIntLine.PreprocessedLine]

        mov     [.char], $09

.getloop:
        lodsb
        test    al, al
        jz      .eol
        cmp     al, $3b
        je      .ignore
        cmp     al, $1a         ; prefix of token
        je      .token
        cmp     al, $22         ; quoted text.
        je      .quoted

        stosb
        cmp     al,','
        jne     .getloop
        mov     al,$20
        stosb
        jmp     .getloop

.quoted:
        mov     al, "'"
        stosb

        lodsd   ; length
        mov     ecx, eax
        rep movsb

        mov     al, "'"
        stosb
        jmp     .getloop

.token:
        movzx   ecx, byte [esi]
        inc     esi
        rep movsb               ; copy the token to the output string.

        cmp     byte [esi], '['
        je      .tab
        cmp     byte [esi], $1a
        jne     .getloop
.tab:
        mov     al, byte [.char]
        mov     byte [.char], $20
        stosb
        jmp     .getloop

.ignore:
        mov     al, 0

.eol:
        stosb

        sub     edi, ebx
        mov     [ebx+TMemoryStream.offset], edi

        pop     eax
        pop     ebx edi esi
        return
endp