home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* EXECNEU.PAS *)
- (* (c) 1990 Christian Büchel & TOOLBOX *)
- (* ------------------------------------------------------ *)
- USES Dos;
-
- VAR
- Error : INTEGER;
-
- {$IFDEF VER40}
- FUNCTION GetEnv(EnvVar : STRING) : STRING;
- (* Ersetzt die Funktion GetEnv in Turbo 5.0 *)
- LABEL
- ex1, ex2;
- VAR
- envadr : WORD;
- super_dummy : STRING;
- i, lang, start : BYTE;
- BEGIN
- FOR i := 1 TO Length(EnvVar) DO
- EnvVar[i] := UpCase(EnvVar[i]);
- envadr := MemW[PrefixSeg:$2C];
- super_dummy[0] := #255;
- (* Explizit Stringlänge auf 255 setzen *)
- Move(Mem[envadr:0], super_dummy[1], 255);
- (* Environment nach super_dummy kopieren
- und als normalen String behandeln *)
- FOR i := Pos(EnvVar, super_dummy) +
- Length(EnvVar) + 1 TO 255 DO
- IF (super_dummy[i] <> '=') AND
- (super_dummy[i] <> ' ') THEN BEGIN
- start := i;
- GOTO ex1;
- END;
- ex1:
- FOR i := start TO 255 DO
- IF Ord(super_dummy[i]) = 00 THEN BEGIN
- lang := i-start;
- GOTO ex2;
- END;
- ex2:
- GetEnv := Copy(super_dummy, start, lang);
- IF Pos(EnvVar, super_dummy) = 0 THEN GetEnv := '';
- (* Gesuchte Variable nicht in Environment *)
- END;
- {$ENDIF}
-
- FUNCTION ExecNeu(Path, Command : STRING) : INTEGER;
- LABEL
- ExitPoint;
- CONST
- MindStack : WORD = 1000;
- MindRAMforExec : WORD = 20000;
- TYPE
- SegOfs = RECORD
- O, S : WORD;
- END;
- VAR
- AltStartFragList,
- NeuStartFragList,
- RAM_Ende : POINTER;
- Allocated,
- SizeOfFragList,
- ParasToKeep,
- ParasKomplett,
- ParasForExec : WORD;
- Regs : Registers;
-
- FUNCTION PtrDiff(Hi, Lo : POINTER) : LONGINT;
- VAR
- High : SegOfs ABSOLUTE Hi;
- Low : SegOfs ABSOLUTE Lo;
- BEGIN
- PtrDiff := (LONGINT(High.S) SHL 4 + High.O) -
- (LONGINT(Low.S) SHL 4 + Low.O);
- END;
-
- FUNCTION StartFragList : POINTER;
- { FreePtr zeigt nicht direkt auf Fragmentliste }
- VAR
- FreeSegOfs : SegOfs ABSOLUTE FreePtr;
- help : POINTER;
- BEGIN
- IF FreeSegOfs.O = 0 THEN
- { Fragmentliste ist leer =>
- Segment + $1000= Beginn Fragmentliste }
- help := Ptr(FreeSegOfs.S + $1000, 0)
- ELSE
- help := Ptr(FreeSegOfs.S + (FreeSegOfs.O SHR 4), 0);
- { Pointer normieren, d.h. Offset 0 }
- StartFragList := help;
- END;
-
- FUNCTION SetBlock(VAR Paragraphs : WORD) : BOOLEAN;
- { Den einem Programm zugeteilten Speicher verändern }
- BEGIN
- WITH Regs DO BEGIN
- AH := $4A;
- ES := PrefixSeg;
- BX := Paragraphs;
- MsDos(Regs);
- Paragraphs := BX;
- SetBlock := NOT Odd(Flags); { Test auf Carry }
- END;
- END;
-
- BEGIN
- { Größe der Fragmentliste berechnen }
- RAM_Ende := Ptr(SegOfs(FreePtr).S + $1000, 0);
- SizeOfFragList := PtrDiff(RAM_Ende, StartFragList);
-
- { Entweder Fragmentliste auf den Stack oder auf den Heap }
- { Zuerst Stack probieren... }
- IF LONGINT(SizeOfFragList) +
- MindStack < LONGINT(SPtr) THEN BEGIN
- NeuStartFragList := Ptr(SSeg, 0);
- Allocated := 0;
- END ELSE BEGIN
- { Stack zu klein! Genug Platz auf dem Heap ? }
- IF MaxAvail < LONGINT(SizeOfFragList) THEN BEGIN
- { Heap zu klein, abbrechen }
- ExecNeu := 1;
- Exit;
- END;
- { Heap groß genug, RAM für Fragmentliste reservieren ! }
- Allocated := SizeOfFragList;
- IF Allocated > 0 THEN
- GetMem(NeuStartFragList, Allocated);
- SizeOfFragList := WORD(PtrDiff(RAM_Ende,
- StartFragList));
- { Fragmentliste neu berechnen }
- END;
- { Sichern des aktuellen Pointers auf Fragmentliste }
- AltStartFragList := StartFragList;
- { Gesamtmenge Speicher (in Paragraphen (=16 Byte)),
- die dem Programm zur Verfügung stehen. [MCB : 3] }
- ParasKomplett := MemW[Pred(PrefixSeg):3];
- { Wieviel Speicher kann man wieder freigeben ? }
- ParasForExec := Pred(PtrDiff(RAM_Ende, HeapPtr) SHR 4);
- { Wieviel Speicher muß stehen bleiben ? }
- ParasToKeep := ParasKomplett - ParasForExec;
- { Reicht freigemachter Speicher für Exec ? }
- IF (ParasForExec > 0) AND
- (ParasForExec < (MindRAMforExec SHR 4)) THEN BEGIN
- ExecNeu := 4;
- GOTO ExitPoint;
- END;
- { Mit DOS-Funktion Speicher verkleinern }
- IF NOT SetBlock(ParasToKeep) THEN BEGIN
- ExecNeu := 2;
- GOTO ExitPoint;
- END;
- { Fragmentliste wird kopiert (Stack oder Heap) s.o. }
- Move(AltStartFragList^, NeuStartFragList^,
- SizeOfFragList);
-
- {$IFDEF VER40}
- GetIntVec($23, TurboInt23);
- GetIntVec($24, TurboInt24);
- SetIntVec($23, SaveInt23);
- SetIntVec($24, SaveInt24);
- {$ELSE}
- SwapVectors;
- {$ENDIF}
-
- Exec(Path, Command);
-
- {$IFDEF VER40}
- SetIntVec($23,TurboInt23);
- SetIntVec($24,TurboInt24);
- {$ELSE}
- SwapVectors;
- {$ENDIF}
- { Mit DOS-Funktion Speicher wieder vergrößern }
- IF NOT SetBlock(ParasKomplett) THEN BEGIN
- ExecNeu := 3;
- GOTO ExitPoint;
- { Sollte dieser Fehler je auftreten => CRASH }
- END;
- { Fragmentliste zurückkopieren }
- Move(NeuStartFragList^, AltStartFragList^,
- SizeOfFragList);
- ExecNeu := DosError;
-
- ExitPoint:
- { Eventuell belegten Heap freigeben, auch im Fehlerfall }
- IF Allocated <> 0 THEN
- FreeMem(NeuStartFragList, Allocated);
- END;
-
- BEGIN { Kleiner Test }
- WriteLn(GetEnv('COMSPEC'),' /C DIR');
- Error := ExecNeu(GetEnv('COMSPEC'),' /C DIR');
- WriteLn(Error);
- END.
- (* ------------------------------------------------------ *)
- (* Ende von EXECNEU.PAS *)