home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* PROJECT.PAS *)
- (* Auflistung aller zu einem Turbo Pascal-Programm *)
- (* gehörenden Dateien *)
- (* (c) 1989 TOOLBOX & Karsten Gieselmann *)
- (* ------------------------------------------------------ *)
- {$R-,S-,I-,V-,B-,N-}
- {$M 4096, 8192, 8192}
- (* möglichst viel Speicher für TPC übrig lassen! *)
- PROGRAM Project;
-
- USES
- Crt, Dos; (* benötigte Units *)
-
- CONST
- Version = 'PROJECT 1.0';
- MaxFiles = 100; (* Maximalzahl von Projektdateien *)
- Compiler = 'C:\TURBO5\TPC.EXE';
- (* Pfad für Kommandozeilen-Compiler *)
- Options = '/TC:\TURBO/M ';
- (* fixer Teil der Kommandozeile *)
- Units = ''; (* zu TPC.CFG alternative Pfadangaben *)
- Includes = '';
- Objects = '';
-
- VAR
- SaveInt21 : POINTER; (* alter INT-21-Vektor *)
- k,LastFile : WORD;
- CurrentFile : STRING; (* aktueller Listeneintrag *)
- Overflow : BOOLEAN; (* Liste zu groß? *)
- RequiredFile : ARRAY[1..MaxFiles] OF ^STRING;
- (* Liste der Dateien *)
-
- (* ------ allgemeiner Pattern-Matching-Algorithmus ------ *)
-
- FUNCTION Match(Source, Pattern : STRING) : BOOLEAN;
- (* prüft, ob die durch "Pattern" gegebene Zeichenkette,
- die beliebig mit Wildcards "?" (ein Zeichen) und "*"
- (beliebig viele Zeichen) durchsetzt sein kann, mit
- "Source" (darf keine Wildcards enthalten!)
- übereinstimmt. Groß- und Kleinschreibung werden dabei
- nicht unterschieden.
- Beispiel: "T*B?x*SP??Z*" stimmt mit
- "Toolbox ist Spitze!" überein. *)
-
- TYPE
- Result = (Failed, Passed, Scanning);
-
- VAR
- PatternLen : BYTE ABSOLUTE Pattern;
- SourceLen : BYTE ABSOLUTE Source;
-
- FUNCTION MatchSubStr(s : BYTE; p : BYTE) : Result;
- (* Test auf Übereinstimmung der Teilstrings
- ab Pattern[p], Source[s] *)
- VAR
- State : Result;
- BEGIN
- IF PatternLen = 0 THEN
- State := Passed
- (* triviale Übereinstimmung: leeres Muster *)
- ELSE BEGIN
- State := Scanning;
- REPEAT
- IF (s > SourceLen) AND (p > PatternLen) THEN
- (* Muster und Zeichenvorrat... *)
- State := Passed (* ...vollständig abgearbeitet *)
- ELSE
- IF p > PatternLen THEN
- State := Failed
- (* Muster vorzeitig erschöpft! *)
- ELSE
- IF Pattern[p] = '*' THEN
- IF p = PatternLen THEN
- (* Jokerzeichen entspricht.... *)
- State := Passed
- (* ...restlichem Zeichenvorrat *)
- ELSE
- REPEAT (* rekursiver Restvergleich *)
- State := MatchSubStr(s, p+1);
- Inc(s);
- UNTIL (State = Passed) OR (s > SourceLen)
- ELSE
- IF (Upcase(Pattern[p]) <> Upcase(Source[s]))
- AND (Pattern[p] <> '?') THEN
- State := Failed (* keine Übereinstimmung *)
- ELSE BEGIN
- Inc(s); Inc(p);
- (* Übereinstimmung, nächstes Zeichen *)
- END;
- UNTIL State <> Scanning;
- END;
- MatchSubStr := State;
- END;
-
- BEGIN
- Match := (MatchSubStr(1, 1) = Passed);
- END;
-
- FUNCTION MatchesMask(FileName : STRING) : BOOLEAN;
- (* stimmt "FileName" mit einer
- der angegebenen Masken überein? *)
- VAR
- Matched : BOOLEAN;
- k : WORD;
- BEGIN
- IF ParamCount >= 2 THEN BEGIN
- (* Übereinstimmung mit Masken überprüfen *)
- k := 2;
- Matched := FALSE;
- WHILE (k <= ParamCount) AND NOT Matched DO BEGIN
- Matched := Matched OR Match(FileName, ParamStr(k));
- Inc(k);
- END;
- MatchesMask := Matched;
- END ELSE
- MatchesMask := TRUE;
- (* keine Maskenangabe: dann *.* annehmen! *)
- END;
-
- (* neue Service-Routine für DOS-Funktionsinterrupt 21H *)
-
- {$F+}
- PROCEDURE Int21(Flags,CS,IP,AX,BX,CX,DX,
- SI,DI,DS,ES,BP : WORD); INTERRUPT;
- {$F-}
-
- TYPE
- IntRegisters = RECORD CASE BYTE OF
- 1 : (BP,ES,DS,DI,SI,
- DX,CX,BX,AX,IP,CS,Flags : WORD);
- 2 : (Dummy : ARRAY[1..5] OF WORD;
- DL,DH,CL,CH,BL,BH,AL,AH : BYTE);
- END;
-
- CONST (* Aufrufzähler: die ersten
- beiden Dateien.. *)
- NumberOfCalls : WORD = 0; (* ..TPC.CFG, TURBO.TPL sollen
- ignoriert werden! *)
- VAR
- Regs : IntRegisters ABSOLUTE BP;
- Len : BYTE ABSOLUTE CurrentFile;
-
- PROCEDURE ChainInt(Regs: IntRegisters; Address : POINTER);
- INLINE($5B/$58/$5E/$1F/$87/$5C/$0E/$87/$44/$10/$8B/$54/
- $16/$52/$9D/$8C/$DA/$FA/$8E/$D2/$89/$F4/$FB/$5D/
- $07/$1F/$5F/$5E/$5A/$59/$CB);
- BEGIN
- WITH Regs DO BEGIN
- IF AH = $02 THEN BEGIN
- (* Ausgaben von TPC direkt auf den Bildschirm... *)
- Write(Chr(DL)); Exit;
- (* ...um die Liste vollständig zu isolieren! *)
- END;
- IF AH = $3D THEN BEGIN
- Inc(NumberOfCalls);
- IF (NumberOfCalls > 2) AND NOT Overflow THEN BEGIN
- (* Projektdatei! *)
- Len := 0;
- WHILE Chr(Mem[DS:DX+Len]) <> #0 DO BEGIN
- (* Dateinamen auslesen *)
- Inc(Len);
- CurrentFile[Len] := Chr(Mem[DS:DX+Len-1]);
- END;
- k := 1;
- WHILE (k <= LastFile) AND
- (CurrentFile <> RequiredFile[k]^) DO
- Inc(k);
- IF MatchesMask(CurrentFile) AND
- (k > LastFile) THEN BEGIN
- GetMem(RequiredFile[k], Len+1);
- Move(CurrentFile, RequiredFile[k]^, Len+1);
- (* in Liste eintragen *)
- Inc(LastFile);
- Overflow := LastFile > MaxFiles;
- END;
- END;
- END;
- END;
- ChainInt(Regs, SaveInt21);
- END;
-
- BEGIN
- WriteLn(^M^J, Version);
- IF (ParamCount = 0) OR (ParamStr(1) = '?') THEN BEGIN
- WriteLn('Syntax: PROJECT Name [Dateigruppen] ',
- '[>Output]'); Halt;
- END;
- WriteLn;
- LastFile := 0;
- Overflow := FALSE;
- GetIntVec($21, SaveInt21);
- (* Funktionsinterrupt umleiten *)
- SetIntVec($21, @Int21);
- Exec(Compiler,Options+Units+Objects+Includes+ParamStr(1));
- SetIntVec($21, SaveInt21);
- IF Overflow THEN
- WriteLn('Too many files, project file list not written');
- Assign(Output, ''); Rewrite(Output);
- IF NOT Overflow THEN (* Projektdateien ausgeben *)
- FOR k := 1 TO LastFile DO
- WriteLn(RequiredFile[k]^);
- END.
- (* ------------------------------------------------------ *)
- (* Ende von PROJECT.PAS *)