175 lines
4.2 KiB
ObjectPascal

// SPDX-License-Identifier: LGPL-3.0-linking-exception
unit ConstFile;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, ReleaserTypes;
type
{ TConstFile }
TConstFile = class(TReleaserObject)
private
FFilename, FConstname: String;
FSourceCode: string;
FChanged: boolean;
procedure AnalyzeVersionLine(ALine: string; out AValueStart,
AValueLength: integer);
public
constructor Create(AParameters: TStringList; ALogicDir: string); override;
destructor Destroy; override;
procedure Save; override;
function TryVersion(out AValue: TVersion): boolean;
procedure GetVersions(AVersionList: TStringList); override;
procedure UpdateVersion(AVersion: TVersion); override;
end;
implementation
{ TConstFile }
procedure TConstFile.AnalyzeVersionLine(ALine: string; out AValueStart, AValueLength: integer);
var
s: String;
p: integer;
begin
AValueStart := 0;
AValueLength:= 0;
s := ALine;
p := pos(FConstname+' ',s);
if (p<> 0) and ((p=1) or (s[p-1] in[#0..#32])) then
begin
inc(p, length(FConstName));
while (p <= length(s)) and (s[p] in[#0..#32]) do inc(p);
if (p <= length(s)) and (s[p] = '=') then
begin
inc(p);
while (p <= length(s)) and (s[p] in[#0..#32]) do inc(p);
AValueStart := p;
while (p <= length(s)) and (s[p] in['0'..'9']) do inc(p);
AValueLength:= p-AValueStart;
exit;
end;
end;
end;
constructor TConstFile.Create(AParameters: TStringList; ALogicDir: string);
var
ver: TVersion;
str: TStringStream;
stream: TFileStream;
begin
inherited Create(AParameters, ALogicDir);
ExpectParamCount(2);
FFilename := ExpandFileName(ReplaceVariables(Param[0]));
FConstname := Param[1];
stream := nil;
str := nil;
try
stream := TFileStream.Create(FFilename, fmOpenRead);
str := TStringStream.Create('');
if str.CopyFrom(stream, stream.Size)<>stream.Size then
raise exception.Create('Unable to read file');
FSourceCode := str.DataString;
finally
str.Free;
stream.Free;
end;
if TryVersion(ver) then
writeln('Code file "',ExtractFileName(FFilename),'" version ',VersionToStr(ver))
else
writeln('Code file "',ExtractFileName(FFilename),'" undefined version');
end;
destructor TConstFile.Destroy;
begin
inherited Destroy;
end;
procedure TConstFile.Save;
var
stream: TFileStream;
begin
if FChanged then
begin
writeln('Updating code file "',ExtractFileName(FFilename),'"');
stream := TFileStream.Create(FFilename, fmCreate);
try
if FSourceCode <> '' then
stream.WriteBuffer(FSourceCode[1], length(FSourceCode));
finally
stream.Free;
end;
end;
end;
function TConstFile.TryVersion(out AValue: TVersion): boolean;
var
valueStart,valueLen,errPos: integer;
verValue: LongWord;
begin
AValue.Major:= 0;
AValue.Minor:= 0;
AValue.Release:= 0;
AValue.Build:= 0;
AnalyzeVersionLine(FSourceCode, valueStart, valueLen);
if valueStart > 0 then
begin
val(copy(FSourceCode, valueStart, valueLen), verValue, errPos);
if errPos = 0 then
begin
AValue.Major:= verValue div 1000000;
AValue.Minor := (verValue div 10000) mod 100;
AValue.Release := (verValue div 100) mod 100;
AValue.Build := verValue mod 100;
exit(true);
end;
end;
result := false;
end;
procedure TConstFile.GetVersions(AVersionList: TStringList);
var
ver: TVersion;
verStr: String;
begin
if TryVersion(ver) then
begin
verStr := VersionToStr(ver);
if AVersionList.IndexOf(verStr)=-1 then AVersionList.Add(verStr);
end;
end;
procedure TConstFile.UpdateVersion(AVersion: TVersion);
var
ver: TVersion;
newValue, valueStart, valueLength: Integer;
s: String;
begin
newValue := AVersion.Major*1000000 + AVersion.Minor*10000 + AVersion.Release*100 + AVersion.Build;
if TryVersion(ver) then
begin
if AVersion<>ver then
begin
AnalyzeVersionLine(FSourceCode, valueStart,valueLength);
if valueStart <> 0 then
begin
s := FSourceCode;
delete(s, valueStart,valueLength);
insert(IntToStr(newValue), s,valueStart);
FSourceCode := s;
FChanged:= true;
end;
end;
end else
writeln('Please add manually a constant ',FConstname,' = ',newValue,' in "',ExtractFileName(FFilename),'"');
end;
end.