lazarus-ccr/components/chelper/cconvert.lpr
2011-12-25 03:25:54 +00:00

183 lines
5.0 KiB
ObjectPascal

{ C-to-Pas converter command-line utility part of Lazarus Chelper package
Copyright (C) 2010 Dmitry Boyarintsev skalogryz dot lists at gmail.com
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
program cconvert;
{$mode objfpc}{$H+}
uses
SysUtils,Classes,
ctopasconvert, cparsertypes, cparserutils, cconvconfig, objcparsing,
commonsrcgen;
var
ConfigFile : AnsiString = '';
OutputFile : AnsiString = '';
ConfigFileRO : Boolean = false;
ParseAll : Boolean = false;
ShowCodeSize : Boolean = False; // show the size of code processed
isPascalUnit : Boolean = False; // convert to pascal unit
function StringFromFile(const FileName: AnsiString): AnsiString;
var
fs : TFileStream;
begin
Result:='';
if not FileExists(FileName) then Exit;
try
fs:=TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
SetLength(Result, fs.Size);
fs.Read(Result[1], fs.Size);
finally
fs.Free;
end;
except
end;
end;
procedure InitSettings(cfg: TConvertSettings);
var
i : Integer;
p : AnsiString;
fn : AnsiString;
begin
i:=1;
while i<=Paramcount do begin
p:=AnsiLowerCase(ParamStr(i));
if p='-cfg' then begin
inc(i);
fn:=Trim(Paramstr(i));
ConfigFile:=fn;
if FileExists(fn) then cconvconfig.LoadFromFile(fn, cfg);
end else if p='-ro' then
ConfigFileRO:=True
else if p='-defines' then begin
inc(i);
cfg.CustomDefines:=cfg.CustomDefines+' ' + StringFromFile(ParamStr(i));
end else if p='-o' then begin
inc(i);
OutputFile:=ParamStr(i);
end else if p='-all' then begin
ParseAll:=True
end else if p='-pasunit' then
isPascalUnit:=True;
inc(i);
end;
end;
procedure PrintHelp;
begin
writeln('cconvert - c to pascal convert utility');
writeln('possible options:');
writeln(' -all - convert the whole header to pascal, instead of a first entity');
writeln(' -o filename - specify the output file. if not specified, outputs to stdout');
writeln(' -ro - prevent the configuration file from modifications (adding new types, etc)');
writeln(' -cfg filename - specifies the configuration file');
writeln(' -defines filename - macros definition file. should be in C-preprocessor format');
writeln(' -showunparsed - writes out unprased entities by their classname (for debugging only)');
writeln(' -codesize - show two numbers of the code processed (used by Chelper)');
writeln(' -pasunit - generates a pascal unit');
end;
procedure ReadParams(var InputFileName: String);
var
i : integer;
s : string;
begin
for i:=1 to ParamCount do begin
s:=LowerCase(ParamStr(i));
if (s='-h') or (s='-help') or (s='-?') then begin
PrintHelp;
Halt;
end else if s='-showunparsed' then
DoDebugEntities:=True;
end;
InputFileName:=ParamStr(ParamCount);
end;
function GetPascalUnitName(const UnitName: String): String;
begin
Result:=ChangeFileExt(UnitName, '');
end;
procedure AddPascalUnit(outs: TStrings; const UnitName: String);
begin
if not Assigned(outs) then Exit;
outs.Insert(0, 'unit '+UnitName+';');
outs.Insert(1, '');
outs.Insert(2, 'interface');
outs.Add( 'implementation');
outs.Add( 'end.');
end;
var
inps, outs : TStringList;
i : Integer;
p : TPoint;
cfg : TConvertSettings;
err : TErrorInfo;
fn : String;
begin
if ParamCount=0 then Exit;
ReadParams(fn);
if not FileExists(fn) then begin
writeln('file doesn''t exist: ', fn);
Exit;
end;
inps := TStringList.Create;
outs := TStringList.Create;
cfg:=TConvertSettings.Create;
try
InitSettings(cfg);
inps.LoadFromFile(ParamStr(ParamCount));
outs.Text:=ConvertCode(inps.Text, p, ParseAll, err, cfg);;
if ShowCodeSize then outs.Insert(0, Format('%d %d', [p.Y,p.X]));
if err.isError then outs.Insert(0, Format('error %d %d %s',[err.ErrorPos.Y, err.ErrorPos. X, err.ErrorMsg]) );
if isPascalUnit then begin
AddPascalUnit(outs, GetPascalUnitName(fn));
end;
if OutputFile<>'' then
outs.SaveToFile(OutputFile)
else
for i:=0 to outs.Count-1 do
writeln(outs[i]);
finally
if not ConfigFileRO and (ConfigFile<>'') then begin
ForceDirectories(ExtractFilePath(ConfigFile));
try
cconvconfig.SaveToFile(ConfigFile, cfg);
except
end;
end;
cfg.Free;
inps.Free;
outs.Free;
end;
end.