1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
program extractor2;
{$APPTYPE CONSOLE}
uses
Classes, SysUtils, IOUtils;
function SubString(const aSource: string; aStart: integer; aEnd: integer = MAXINT): string;
begin
result := Copy(aSource, aStart, aEnd - aStart + 1);
end;
var
allText: string;
i, j, k: integer;
c: char; { Commentaire. }
l: integer; { Chaîne littérale. }
d: boolean; { Directive compilateur. }
tc, tl, td: TStringList; { Tableau commentaires, tableau chaînes littérales, tableau directives. }
begin
tc := TStringList.Create;
tl := TStringList.Create;
td := TStringList.Create;
if (ParamCount = 1) and FileExists(ParamStr(1))then
allText := TFile.ReadAllText(ParamStr(1))
else
allText := TFile.ReadAllText('extractor2.pp');
i := 1;
j := 0;
k := 0;
c := #0; { Pas de commentaire en cours. }
l := 0; { Pas de chaîne littérale en cours. }
d := FALSE; { Pas de directive en cours. }
while i <= Length(allText) do
begin
if c <> #0 then { On est en train de parcourir un commentaire et on en cherche la fin. }
begin
{ La variable c contient le premier caractère trouvé, qui permet de savoir à quel type de
commentaire on a affaire et donc comment il se termine. }
if ((c = '{') and (allText[i] = '}'))
or ((c = '(') and (allText[i] = ')') and (allText[i - 1] = '*'))
or ((c = '/') and (i < Length(allText)) and (allText[i + 1] = #13)) then
begin
k := i;
tc.Append(SubString(allText, j, k));
{ Les commentaires sont purement et simplement supprimés. }
allText := Format(
'%s%s',
[SubString(allText, 1, j - 1), SubString(allText, k + 1)]
);
c := #0;
i := j - 1;
end;
end else
if l <> 0 then { On est en train de parcourir une chaîne littérale et on en cherche la fin. }
begin
if allText[i] = '''' then { Si le caractère courant est un guillemet simple... }
begin
Inc(l); { on le compte. }
{ Si le nombre de guillemets trouvés est pair et que le caractère suivant n'est pas un
guillemet, on a trouvé la fin de la chaîne. }
if (l mod 2 = 0) and (i < Length(allText)) and (allText[i + 1] <> '''') then
begin
k := i;
{ On place une copie de la chaîne, guillemets compris, dans un tableau. }
tl.Append(SubString(allText, j, k));
{ On remplace la chaîne littérale par un motif contenant le numéro de la chaîne, son
index dans le tableau. }
allText := Format(
'%s_litteral_%d_%s',
[SubString(allText, 1, j - 1), tl.Count, SubString(allText, k + 1)]
);
l := 0;
i := j - 1;
end;
end;
end else
{ Même procédure pour les directives. }
if d then
begin
if allText[i] = '}' then
begin
k := i;
td.Append(SubString(allText, j, k));
allText := Format(
'%s_directive_%d_%s',
[SubString(allText, 1, j - 1), td.Count, SubString(allText, k + 1)]
);
d := FALSE;
i := j - 1;
end;
end else
{ Autrement, on cherche le début d'un commentaire, }
if ((allText[i] = '{') and (i < Length(allText)) and (allText[i + 1] <> '$'))
or ((allText[i] = '(') and (i < Length(allText)) and (allText[i + 1] = '*'))
or ((allText[i] = '/') and (i < Length(allText)) and (allText[i + 1] = '/')) then
begin
j := i;
c := allText[i];
end else
{ ou d'une chaîne littérale, }
if allText[i] = '''' then
begin
j := i;
l := 1;
end else
{ ou d'une directive. }
if ((allText[i] = '{') and (i < Length(allText)) and (allText[i + 1] = '$')) then
begin
j := i;
d := TRUE;
end;
Inc(i);
end;
TFile.WriteAllText('1.txt', allText);
with TStringList.Create do
begin
for i := 0 to tc.Count - 1 do Append(Format('comment=[%s]', [tc[i]]));
for i := 0 to tl.Count - 1 do Append(Format('literal=[%s]', [tl[i]]));
for i := 0 to td.Count - 1 do Append(Format('directive=[%s]', [td[i]]));
SaveToFile('2.txt');
Free;
end;
tc.Free;
tl.Free;
td.Free;
end. |
Partager