Ok, here's another one, as you can see i really like pointers

There's probably ways to improve this, but i wont do it..for now i'm just happy that it works
If you have many many lines in a row with linecontinuation and really long comments you will have to enlarge the string buffer that PB uses internally. Though i doubt this will happend, if one use >64kb of comments one should consider writing a book instead
Code: Select all
;
#EOL$ = Chr(13)+Chr(10)
; Init
Dim hash.b(255)
hash(' ') = 1
hash(';') = 1
hash(10) = 1
hash(13) = 1
hash('"') = 1
hash(9) = 1
hash(39) = 1
Procedure ParseFile(InFile.s, OutFile.s)
DefType.s comment, commentbuffer, dbgtext
DefType.l length, char, quote, pos, posline, linecontinuation
DefType.byte *ibuffer, *obuffer, *start, *endline, *iptr, *optr, *commentstart
If ReadFile(0, InFile)
length = Lof()
If length
*ibuffer = AllocateMemory(length+10) : *obuffer = AllocateMemory(length+10)
If *ibuffer And *obuffer
ReadData(*ibuffer, length)
Else
length = 0
EndIf
EndIf
CloseFile(0)
EndIf
If length = 0
ProcedureReturn 0
EndIf
*optr = *obuffer
*iptr = *ibuffer
Repeat
*start = *iptr
Repeat
char = *iptr\b & $ff
If char = '"' Or char = 39 ; Single or double quote
posline = 0
If quote
If quote = char ; Found matching quotes
quote = 0
EndIf
Else
quote = char
EndIf
ElseIf quote = 0
If char = ' ' Or char = 9 ; white space
If *iptr = *start And linecontinuation
*start + 1
EndIf
prevchar = ' ' : *iptr+1 : Continue
ElseIf char = ';' ; comment to end of line
*commentstart = *iptr
Repeat
; check for EOL or EOF
If *iptr\b = 10 Or *iptr\b = 0
If PeekB(*iptr-1) = 13
*endline = *iptr-1
Else
*endline = *iptr
EndIf
Break 2
EndIf
*iptr+1
ForEver
ElseIf char = '_' And prevchar = ' '
; Maybe it's a line continuation
posline = *iptr
ElseIf hash(char) = 0
posline = 0
EndIf
EndIf
; check for EOL or EOF
If char = 10 Or char = 0; End of line/file?
If *iptr > *start And PeekB(*iptr-1) = 13
*endline = *iptr-1
Else
*endline = *iptr
EndIf
Break
EndIf
prevchar = char
*iptr+1
ForEver
If posline
pos = posline
ElseIf linecontinuation
If *commentstart
pos = *commentstart
Else
pos = *endline
EndIf
Else
pos = *endline
EndIf
length = pos - *start
CopyMemory(*start, *optr, length) : *optr + length; + 1
If linecontinuation
If *commentstart
commentbuffer + PeekS(*commentstart, *endline-*commentstart)
EndIf
commentbuffer + #EOL$
If posline = 0
linecontinuation = 0
length = PokeS(*optr, comment+#EOL$) : *optr + length ;+ 1
length = PokeS(*optr, commentbuffer) : *optr + length ;+ 1
comment = "" : commentbuffer = ""
EndIf
ElseIf posline
linecontinuation = 1
If *commentstart
comment = PeekS(*commentstart, *endline-*commentstart)
Else
comment = ""
EndIf
ElseIf *iptr\b <> 0
PokeS(*optr, #EOL$) : *optr+2
EndIf
quote = 0 : prevchar = 0
posline = 0 : *endline = 0 : *commentstart = 0
*iptr+1
Until *iptr\b = 0
If *optr <> *obuffer
If CreateFile(0, OutFile)
WriteData(*obuffer, *optr-*obuffer)
CloseFile(0)
EndIf
EndIf
FreeMemory(*ibuffer) : FreeMemory(*obuffer)
ProcedureReturn 1
EndProcedure
file.s = OpenFileRequester("Select file", "", "All Files|*.*", 0)
If file <> ""
t1.l = GetTickCount_()
For i = 0 To 100
ParseFile(file, file+"$new.pb")
Next
t2.l = GetTickCount_()
MessageRequester("Time", Str(i-1)+" iterations took "+Str(t2-t1)+"ms.")
EndIf