Z,
Here is a tokeniser that does not strip leading white space or empty lines. Its in its own test piece.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
line_tokeniser PROTO :DWORD
get_lcnt PROTO :DWORD
.data
caesar \
db "Friends, Romans, countrymen, lend me your ears;",13,10
db " I come to bury Caesar, not to praise him.",13,10,13,10
db " The evil that men do lives after them;",13,10
db "The good is oft interred with their bones;",13,10,0
ptxt dd caesar
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
print chr$(13,10)
inkey "Thats all folks, press a key to exit..."
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL pMem :DWORD
LOCAL lcnt :DWORD
mov pMem, rv(line_tokeniser,ptxt) ; tokenise text
mov lcnt, ecx ; save the line count
push esi
push edi
mov esi, pMem ; load array into ESI
mov edi, lcnt ; use EDI as the counter
@@:
print [esi],13,10 ; display each line of text
add esi, 4 ; increment to next pointer
sub edi, 1 ; dec the counter
jnz @B ; loop back if not zero
pop edi
pop esi
free pMem ; release memory from tokeniser
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
line_tokeniser proc src:DWORD
; ---------------------------------------------------
; tokeniser for CRLF delimited text
; ---------------------------------------------------
; replaces the ascii 13 with zero and writes apointer
; to the allocated memory as an array of pointers
; return value in EAX = pointer array address
; return value in ECX = the line count
; array address must be de-allocated using
; GlobalFree() or the macro "free".
; ---------------------------------------------------
LOCAL lcnt :DWORD
LOCAL pMem :DWORD
LOCAL alen :DWORD
push src
call get_lcnt ; get the line count
mov lcnt, eax ; store line count in variable
lea eax, [eax*4] ; set pointer array length
mov alen, eax ; store the array size in alen
mov pMem, alloc(alen) ; allocate the pointer array
mov edx, src ; source address in ESI
mov ecx, pMem ; pointer array address in EBX
mov [ecx], edx ; load array address into 1st member of array
add ecx, 4
sub edx, 1
lbl1:
add edx, 1
movzx eax, BYTE PTR [edx] ; zero extend byte into EAX
test eax, eax ; test for zero
jz lbl2 ; exit loop on zero
cmp eax, 13 ; test for ascii 13
jne lbl1 ; short loop back if not 13
mov BYTE PTR [edx], 0 ; write terminator at ascii 13 location
add edx, 2 ; step over ascii 13 and 10
mov [ecx], edx ; write the next line start to pointer
add ecx, 4 ; increment to next pointer
jmp lbl1 ; long loop after writing pointer
lbl2:
mov ecx, lcnt ; return the line count in ECX
mov eax, pMem ; the array pointer in EAX
ret
line_tokeniser endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
get_lcnt proc src:DWORD
; --------------------------------------
; count ascii 13 to determine line count
; --------------------------------------
mov edx, [esp+4] ; the source address
sub edx, 1
xor eax, eax
jmp lbl1
pre:
add eax, 1 ; increment the counter
lbl1:
; -----------
; unroll by 4
; -----------
add edx, 1
movzx ecx, BYTE PTR [edx]
cmp ecx, 13
je pre
test ecx, ecx
jz lbl2
add edx, 1
movzx ecx, BYTE PTR [edx]
cmp ecx, 13
je pre
test ecx, ecx
jz lbl2
add edx, 1
movzx ecx, BYTE PTR [edx]
cmp ecx, 13
je pre
test ecx, ecx
jz lbl2
add edx, 1
movzx ecx, BYTE PTR [edx]
cmp ecx, 13
je pre
test ecx, ecx
jnz lbl1
lbl2:
ret 4
get_lcnt endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start