Source file: /~heha/hs/dos/dosmisc.zip/SRC/SETINI.PAS

{$M 16384,0,0}
{$I+,G+,Q-,R-}
program setini;
uses WinDos,Strings,Parser;
{Setzt in INI-Datei <arg1> in Sektion <arg2> den Schlüssel <arg3> auf <arg4>}

procedure Usage;
 begin
  WriteLn(
'SETINI (h#s 09/02): Analogon zu Get/WritePrivateProfileString'#13#10+
'Argumente: <dateiname> [<multikey_action>] <[sektion]> [<schlüssel> [<wert>]]'#13#10+
'<dateiname> und <[sektion]> sind Pflicht; Sektion mit [] schreiben!');
  WriteLn(
'Präfix "!" vor Dateinamen steht für Windows-Verzeichnis (%windir%)'#13#10+
'Extra-Funktionen: Leere Sektion [] setzt Variable in Nicht-Windows-.INI'#13#10+
'Kein Wert: Schlüssel löschen. Kein Schlüssel: Sektion löschen.');
  WriteLn(
'<wert> darf Leerzeichen enthalten, <schlüssel> und <[sektion]> nur mittels ""!'#13#10+
'<multikey_action>=ADD: Hinzufügen, <multikey_action>=DEL: Löschen'#13#10+
'<multikey_action>=GET: Nach Umgebungsvariable <wert> lesen (sonst nur stdout)');
  WriteLn(
'Beispiele:'#13#10+
'Windows-Shell ändern:    setini !system.ini [boot] Shell c:\vc\vc.com'#13#10+
'ein VxD hinzufügen:      setini !system.ini ADD [386Enh] device myvxd.386'#13#10+
'ein anderes VxD löschen: setini !system.ini DEL [386Enh] device othervxd.386');
  WriteLn(
'3.1: Dr.Watson nützlich machen: setini !win.ini "[Dr. Watson]" ShowInfo par sou'#13#10+
'DOS-CDROM-Treiber setzen: setini c:\config.sys ADD [common] device mycdrom.sys');
  halt;
 end;

function IsVar(Env,l:PChar):Boolean;
 var
  SP1: PChar;
  len: Word;
 begin
  IsVar:=false;
  SP1:=StrScan(Env,'=');
  len:=StrLen(l);
  if (SP1<>nil) and (SP1-Env=len) and (StrLIComp(Env,l,len)=0)
  then IsVar:=true;
 end;

var
 EnvSize: Integer;

function GetParentEnvPtr: PChar; assembler;
 asm	mov	es,[PrefixSeg]
	mov	es,es:[$16]
	mov	dx,es:[$2C]
	dec	dx
	mov	es,dx
	mov	ax,es:[3]	{Länge Env-Speicher}
	shl	ax,4		{in Bytes}
	mov	[EnvSize],ax
	inc	dx
	xor	ax,ax
 end;

function SetEnv(l,r:PChar): Boolean;	{Arg[4] und SP1}
 type
  PInteger=^Integer;
  PtrRec=record
   ofs,seg: Word;
  end;
 var
  SPE,SP2,SP3: PChar;
  Shift,BytesFree: Integer;
 begin
  SetEnv:=false;
  SPE:=GetParentEnvPtr;
  SP2:=nil;
  while SPE^<>#0 do begin
   if IsVar(SPE,l) then begin
    SP2:=SPE;
    SP3:=StrEnd(SPE)+1;		{Hier ersetzen}
   end;
   SPE:=StrEnd(SPE)+1;
  end;
  if SP2=nil then begin
   SP2:=SPE;	{Zuletzt einfügen}
   SP3:=SPE;
  end;
  Inc(SPE);
  if PInteger(SPE)^=1 then SPE:=StrEnd(SPE+2)+1;
  Shift:=(StrLen(l)+StrLen(r)+2)	{Verschiebung nach hinten}
  -(PtrRec(SP3).ofs-PtrRec(SP2).ofs);	{Verschiebung nach vorn}
  BytesFree:=EnvSize-PtrRec(SPE).ofs-Shift;{Platz am Ende minus Schiebung}
  if BytesFree<0 then begin
   WriteLn('Umgebungsspeicher voll!');
   exit;
  end;
  Move(SP3^,(SP3+Shift)^,PtrRec(SPE).ofs-PtrRec(SP3).ofs);
  StrCopy(SP2,l);
  StrCat(SP2,'=');
  StrCat(SP2,r);
  SetEnv:=true;
 end;

var
 Arg: array[1..4] of PChar;
 I: Integer;
 f,f2: Text;
 FName1,FName2: array[0..127] of Char;
 S,Line: array[0..255] of Char;
 InSection,CopyLine,MultiKey: Boolean;
 MultiKey_Add, MultiKey_Del: Boolean;
 MultiKey_Get, BlankLineBefore: Boolean;
 SP1: PChar;
begin
 Arg[4]:=Ptr(PrefixSeg,$81);
 Arg[4][Mem[PrefixSeg:$80]]:=#0;	{nullterminieren}
 for I:=1 to 3 do Arg[I]:=NextItem(Arg[4],Word('"'),DELIM_WhiteSpace);
 if Arg[2][0]=#0 then Usage;
 if Arg[2][0]<>'[' then begin
  MultiKey:=true;
  MultiKey_Add:=StrIComp(Arg[2],'ADD')=0;
  MultiKey_Del:=StrIComp(Arg[2],'DEL')=0;
  MultiKey_Get:=StrIComp(Arg[2],'GET')=0;
  Arg[2]:=Arg[3];	{vorrücken}
  Arg[3]:=NextItem(Arg[4],Word('"'),DELIM_WhiteSpace);
{  for I:=3 to 5 do Arg[I-1]:=Arg[I]GetArgStr(Arg[I-1],I,63);}
  if MultiKey_Get then begin
   StrUpper(Arg[4]);	{Umgebungsvariable}
   if Arg[3][0]=#0 then begin
    WriteLn('FATAL: Parameter <schlüssel> muss angegeben werden!');
    halt;
   end;
   if StrScan(Arg[4],' ')<>nil then begin
    WriteLn('FATAL: Zu viele Parameter!');
    halt;
   end;
  end else begin
   if Arg[4][0]=#0 then begin
    WriteLn('FATAL: Alle Parameter müssen angegeben werden!');
    halt;
   end;
  end;
 end else begin
  MultiKey_Add:=Arg[4][0]<>#0;
  MultiKey_Del:=not MultiKey_Add;
 end;
 OneItem(Arg[4],Arg[4],0,0);	{links und rechts "trimmen"}

 if Arg[1][0]='!' then begin	{Windows-Verzeichnis (sofern Windows läuft)}
  SP1:=GetEnvVar('windir');	{arbeitet zum Glück auch mit Kleinbuchstaben}
  if SP1=nil then SP1:=GetEnvVar('winbootdir');	{Win9x, schon unter DOS}
  if SP1=nil then begin
   WriteLn('FATAL: %windir%-Verzeichnis angefordert, aber nicht vorhanden!');
   halt;
  end;
  Arg[1][0]:='\';
  if Arg[1][1] in ['\','/'] then Inc(Arg[1]);
  StrCopy(StrECopy(FName1,SP1),Arg[1]);
  Arg[1]:=FName1;		{umsetzen auf Puffer mit Pfad}
 end;
 Assign(f,Arg[1]); {$I-} Reset(f); if IOResult<>0 then; {$I+}
 InSection:=StrIComp(Arg[2],'[]')=0;{Sonderfall Sektion=[]: keine Sektion!}
 if MultiKey_Get then begin
  while (TTextRec(f).mode<>fmClosed) and not eof(f) do begin
   ReadLn(f,S);
   if (StrLen(S)>=2) and (S[0]='[') then begin
    OneItem(S,S,0,0);			{trimmen}
    InSection:=StrIComp(S,Arg[2])=0;
   end else begin
    if InSection then begin
     SP1:=OneItem(S,S,0,Word('=') or DELIM_NilWhenNone);
     if (SP1<>nil) and (StrIComp(S,Arg[3])=0) then begin
      OneItem(SP1,SP1,0,0);		{trimmen}
      break; {KEY gefunden}
     end;
    end;
   end;
   SP1:=nil;
  end;
  if Arg[4][0]<>#0 then begin		{mit EnvVar}
   if SP1<>nil
   then WriteLn(Arg[4],'=',SP1)
   else WriteLn('Sektion/Schlüssel nicht gefunden!');
   SetEnv(Arg[4],SP1);
  end else begin
   WriteLn(SP1);			{bei NIL macht WriteLn nur Linefeed}
  end;
  Close(f);
 end else begin			{Schreibzugriff}
  FileSplit(Arg[1],FName2,nil,nil);
  StrCat(FName2,'tmp.$$$');
  Assign(f2,FName2); ReWrite(f2);
  BlankLineBefore:=false;
  while (TTextRec(f).mode<>fmClosed) and not eof(f) do begin
   ReadLn(f,S);			{S ist zum Zerpflücken}
   StrCopy(Line,S);		{Line ist zum Kopieren}
   CopyLine:=true;
   if (StrLen(S)>=2) and (S[0]='[') then begin
    OneItem(S,S,0,0);			{trimmen}
    if InSection and MultiKey_Add then begin
     WriteLn(f2,Arg[3],'=',Arg[4]);
     BlankLineBefore:=true;		{Leerzeile}
     MultiKey_Add:=false;
    end;
    InSection:=StrIComp(S,Arg[2])=0;
    if InSection and (Arg[3][0]=#0)
    then CopyLine:=false;		{Sektion komplett löschen}
   end else begin
    if InSection then begin
     if MultiKey then begin
      if MultiKey_Add then begin
       WriteLn(f2,Arg[3],'=',Arg[4]);
       MultiKey_Add:=false;		{nur 1x hinzufügen!}
      end;
      if MultiKey_Del then begin
       SP1:=OneItem(S,S,0,Word('=') or DELIM_NilWhenNone);
       if (SP1<>nil) and (StrIComp(S,Arg[3])=0) then begin
	OneItem(SP1,SP1,0,0);
	if (StrIComp(SP1,Arg[4])=0) or (StrPos(SP1,Arg[4])<>nil) then begin
	 CopyLine:=false;
	 MultiKey_Del:=false;		{nur 1x löschen!}
	end;
       end;
      end;
     end else begin
      if Arg[3][0]<>#0 then begin	{sonst: Sektion komplett löschen}
       SP1:=OneItem(S,S,0,Word('=') or DELIM_NilWhenNone);
       if (SP1<>nil) and (StrIComp(S,Arg[3])=0) then begin {KEY gefunden}
	if MultiKey_Add then begin
	 StrCopy(SP1,Arg[4]);
	 MultiKey_Add:=false;		{nur 1x ändern!}
	end else begin
	 CopyLine:=false;
	 MultiKey_Del:=false;		{Löschen OK}
	end;
       end;
      end else begin
       CopyLine:=false;
       MultiKey_Del:=false;		{Löschen OK}
      end;
     end;
    end;
   end;
   if CopyLine then begin
    if S[0]=#0 then BlankLineBefore:=true
    else begin
     if BlankLineBefore then begin
      WriteLn(f2);
      BlankLineBefore:=false;
     end;
     WriteLn(f2,Line);
    end;
   end;
  end;
  if MultiKey_Add then begin
   if not InSection then begin
    WriteLn(f2);
    WriteLn(f2,Arg[2]);
    InSection:=true;
   end;
   WriteLn(f2,Arg[3],'=',Arg[4]);
   MultiKey_Add:=false;
  end;
  if MultiKey_Del then WriteLn('Sektion/Schlüssel nicht gefunden!');
  if TTextRec(f).mode<>fmClosed then begin
   close(f);
   Erase(f);
  end;
  close(f2);
  Rename(f2,Arg[1]);
 end;
end.
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded