Source file: /~heha/hsn/psfilter.zip/parser32.pas

unit parser32;
{Parsen von Kommandozeilen u.ä. "komma-separierten" Listen}
interface
const
 DELIM_NoTrimLeft=$100;
 DELIM_NoTrimRight=$200;
 DELIM_NilWhenNone=$400;	{liefert NIL, wenn KEIN Element mehr da ist}
 DELIM_Whitespace=$800;
 ESCAP_SglQuote=LongInt('''') shl 16;
 ESCAP_DblQuote=LongInt('"') shl 16;
 DELIM_CmdLine=ESCAP_DblQuote or DELIM_WhiteSpace;

function NextItem(var s: PChar; escap_delim:LongInt):PChar;
{escap und delim teilen sich in Low-Byte und High-Byte auf:
 escap.lo=einleitendes Flucht-Zeichen (üblich '"', 0 wenn keine Flucht)
 escap.hi=ausleitendes Flucht-Zeichen (0 wenn gleich einleitendem)
 delim.lo=Trennzeichen, 0 für keins (nur trimmen)
 delim.hi=DELIM_xxx-Bits siehe oben
 Entsprechend der Kommandozeilen-Zusammensetzungs-Strategie der COMMAND.COM
 wird z.B. < "Lange Datei"".""xyz" > zu <Lange Datei.xyz> gewandelt,
 d.h. Flucht-Zeichen schalten hin und her und können selbst nicht mit
 übergeben werden, falls beide gleich sind
 Der String, auf den s zeigt, wird "zerstörend gelesen", die via
 Returnwert (der immer gleich s beim Aufruf ist) Zeichenkette
 ist auch nach mehrfachem Aufruf nicht kaputt.}

function OneItem(d,s: PChar; escap_delim:LongInt):PChar; stdcall;
{eine Modifikation, die als Rückgabewert den vorgerückten Zeiger hat,
 d ist die Zieladresse, d und s dürfen gleich sein; d darf NIL sein
 zum Zählen der Felder}

implementation

procedure IsWS; assembler;
{testet AL auf Weißraum, d.h. $09, $0A, $0D, $20}
 asm	cmp	al,09h
	jz	@@e
	cmp	al,0Ah
	jz	@@e
	cmp	al,0Dh
	jz	@@e
	cmp	al,' '
@@e:	end;

procedure stosb; assembler;
{macht stosb nur wenn EDI<>NIL}
 asm
	or	edi,edi
	jz	@@no
	stosb
@@no:
 end;

function OneItem(d,s: PChar; escap_delim:LongInt):PChar; assembler;
 asm	pushad
	 cld
	 mov	esi,[s]
	 mov	edi,[d]
	 or	esi,esi
	 jz	@@e	{wenn da NIL drinsteht, immer durchreichen!}

	 mov	cx,word ptr [escap_delim+2]
	 mov	dx,word ptr [escap_delim]

	 or	ch,ch
	 jnz	@@1
	 or	cl,cl
	 jz	@@1
	 mov	ch,cl	{gleich machen wenn CH=0 und CL<>0}
@@1:
	 mov	ebx,edi	{Abhack-Zeiger für TrimRight}
	 test	dh,1	{NoTrimLeft?}
	 jnz	@@outquoteloop
@@trimleft:
	 lodsb; or al,al; jz @@raus
	 call	IsWS
	 jz	@@trimleft
	 jmp	@@oq1

@@oq3:	 mov	ebx,edi	{Abhackposition vorrücken}
@@outquoteloop:
	 lodsb; or al,al; jz @@raus
@@oq1:	 cmp	al,cl
	 je	@@inquoteloop
	 test	dh,8	{Whitespace als Trennzeichen?}
	 jnz	@@oq2
	 cmp	al,dl
	 je	@@raus_sep
	 or	edi,edi
	 jz	@@no1
	 stosb
@@no1:	 test	dh,2	{NoTrimRight?}
	 jnz	@@oq3
	 call	IsWS
	 jz	@@outquoteloop
	 jmp	@@oq3
@@oq2:
	 call	IsWS
	 jz	@@raus_sep
	 or	edi,edi
	 jz	@@oq3
	 stosb
	 jmp	@@oq3

@@inquoteloop:
	 lodsb; or al,al; jz @@raus
	 cmp	al,ch
	 je	@@outquoteloop
	 or	edi,edi
	 jz	@@no3
	 stosb
@@no3:	 mov	ebx,edi	{hier jeden Weißraum mitnehmen!}
	 jmp	@@inquoteloop

@@raus:		{ohne Separator: NIL in S einspeichern lassen!}
	 dec	esi	{wieder AUF DIE NULL zurückstellen}
	 test	dh,4
	 jz	@@raus_sep
	 xor	esi,esi
@@raus_sep:
	{Rechts-Trimmung ausführen, gleichzeitig terminieren}
	 or	ebx,ebx
	 jz	@@e
	 mov	byte ptr [ebx],0
	{vorgerücktes S zurückliefern}
@@e:	 mov	[esp+1Ch],esi	{nach EAX}
	popad
 end;

function NextItem(var s: PChar; escap_delim:LongInt):PChar; assembler;
 begin
  NextItem:=s;
  s:=OneItem(s,s,escap_delim);
 end;

end.
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded