2008-03-25 08:17:24 +00:00
|
|
|
{
|
|
|
|
Project1.pas
|
|
|
|
|
|
|
|
Copyright (C) 2008 Dmitry 'Skalogryz' Boyarintsev
|
2008-04-08 10:45:08 +00:00
|
|
|
|
2008-03-25 08:17:24 +00:00
|
|
|
main parser unit
|
|
|
|
}
|
2008-03-04 23:34:41 +00:00
|
|
|
program Project1;
|
|
|
|
|
2008-03-31 12:39:54 +00:00
|
|
|
{$ifdef fpc}
|
|
|
|
{$mode delphi}{$H+}
|
|
|
|
{$else}
|
|
|
|
{$APPTYPE CONSOLE}
|
|
|
|
{$endif}
|
2008-03-04 23:34:41 +00:00
|
|
|
uses
|
2008-04-07 14:06:35 +00:00
|
|
|
Classes,
|
|
|
|
SysUtils,
|
|
|
|
ObjCParserUtils,
|
|
|
|
ObjCParserTypes;
|
2008-03-04 23:34:41 +00:00
|
|
|
|
2008-03-27 15:27:00 +00:00
|
|
|
type
|
|
|
|
// this object is used only for precomile directives handling
|
2008-03-28 10:25:55 +00:00
|
|
|
|
|
|
|
{ TPrecompileHandler }
|
2008-03-27 15:27:00 +00:00
|
|
|
TPrecompileHandler = class(TObject)
|
|
|
|
public
|
2008-04-15 14:13:34 +00:00
|
|
|
hdr : TObjCHeader;
|
2008-03-27 15:27:00 +00:00
|
|
|
procedure OnPrecompile(Sender: TObject);
|
2008-03-28 10:25:55 +00:00
|
|
|
procedure OnComment(Sender: TObject; const Comment: AnsiString);
|
2008-03-27 15:27:00 +00:00
|
|
|
constructor Create(AHeader: TObjCHeader);
|
|
|
|
end;
|
2008-04-07 14:06:35 +00:00
|
|
|
|
2008-03-27 15:27:00 +00:00
|
|
|
procedure TPrecompileHandler.OnPrecompile(Sender: TObject);
|
|
|
|
var
|
|
|
|
parser : TTextParser;
|
|
|
|
preEntity : TPrecompiler;
|
|
|
|
lst : TEntity;
|
|
|
|
prc : TNotifyEvent;
|
|
|
|
begin
|
|
|
|
parser := Sender as TTextParser;
|
|
|
|
//todo: change for something nicier =)
|
|
|
|
prc := parser.OnPrecompile;
|
|
|
|
parser.OnPrecompile := nil;
|
|
|
|
try
|
|
|
|
if parser.Stack.Count > 0 then
|
|
|
|
lst := TEntity(parser.Stack[parser.Stack.Count-1])
|
|
|
|
else
|
|
|
|
lst := nil;
|
|
|
|
|
|
|
|
preEntity := TPrecompiler.Create(lst);
|
|
|
|
preEntity.Parse(parser);
|
|
|
|
lst.Items.Add(preEntity);
|
|
|
|
finally
|
|
|
|
parser.OnPrecompile := prc;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2008-03-28 10:25:55 +00:00
|
|
|
procedure TPrecompileHandler.OnComment(Sender: TObject; const Comment: AnsiString);
|
|
|
|
var
|
|
|
|
parser : TTextParser;
|
|
|
|
cmt : TComment;
|
|
|
|
ent : TEntity;
|
|
|
|
begin
|
|
|
|
if length(Comment) < 2 then Exit;
|
|
|
|
parser := TTextParser(Sender);
|
|
|
|
|
|
|
|
if parser.Stack.Count > 0
|
|
|
|
then ent := TEntity(parser.Stack[parser.Stack.Count-1])
|
|
|
|
else ent := nil;
|
|
|
|
|
|
|
|
if not Assigned(ent) then Exit;
|
|
|
|
cmt := TComment.Create(ent);
|
|
|
|
cmt._Comment := Comment;
|
|
|
|
if IsSubStr('/*', cmt._Comment, 1) then begin
|
|
|
|
cmt._Comment[1] := '(';
|
|
|
|
if isSubStr('*/', cmt._Comment, length(cmt._Comment) - 1) then
|
|
|
|
cmt._Comment[ length(cmt._Comment)] := ')';
|
|
|
|
end;
|
|
|
|
ent.Items.Add(cmt);
|
|
|
|
end;
|
|
|
|
|
2008-03-27 15:27:00 +00:00
|
|
|
constructor TPrecompileHandler.Create(AHeader: TObjCHeader);
|
|
|
|
begin
|
|
|
|
hdr := AHeader;
|
|
|
|
end;
|
|
|
|
|
2008-04-07 14:06:35 +00:00
|
|
|
function ReadAndParseFile(const FileName: AnsiString; outdata: TStrings; var Err: AnsiString): Boolean;
|
2008-03-04 23:34:41 +00:00
|
|
|
var
|
2008-03-28 10:25:55 +00:00
|
|
|
hdr : TObjCHeader;
|
|
|
|
parser : TTextParser;
|
2008-04-02 14:23:02 +00:00
|
|
|
prec : TPrecompileHandler ;
|
2008-03-28 10:25:55 +00:00
|
|
|
s : AnsiString;
|
2008-04-07 14:06:35 +00:00
|
|
|
i, cnt : integer;
|
2008-03-04 23:34:41 +00:00
|
|
|
begin
|
2008-04-07 14:06:35 +00:00
|
|
|
Result :=false;
|
|
|
|
if not FileExists(FileName) then begin
|
|
|
|
Err := 'File not found: ' + FileName;
|
2008-03-25 08:17:24 +00:00
|
|
|
Exit;
|
2008-04-07 14:06:35 +00:00
|
|
|
end;
|
2008-04-15 14:13:34 +00:00
|
|
|
|
2008-03-04 23:34:41 +00:00
|
|
|
s := StrFromFile(FileName);
|
|
|
|
hdr := TObjCHeader.Create;
|
2008-03-27 15:27:00 +00:00
|
|
|
prec := TPrecompileHandler.Create(hdr);
|
2008-03-28 10:25:55 +00:00
|
|
|
parser := TTextParser.Create;
|
|
|
|
parser.TokenTable := CreateObjCTokenTable;
|
2008-03-27 15:27:00 +00:00
|
|
|
|
2008-03-04 23:34:41 +00:00
|
|
|
try
|
2008-03-28 10:25:55 +00:00
|
|
|
parser.Buf := s;
|
2008-03-04 23:34:41 +00:00
|
|
|
try
|
2008-03-28 10:25:55 +00:00
|
|
|
parser.TokenTable.Precompile := '#';
|
|
|
|
parser.OnPrecompile := prec.OnPrecompile;
|
|
|
|
parser.OnComment := prec.OnComment;
|
2008-04-15 14:13:34 +00:00
|
|
|
parser.IgnoreTokens.AddStrings(ConvertSettings.IgnoreTokens);
|
|
|
|
|
2008-03-25 08:17:24 +00:00
|
|
|
hdr._FileName := ExtractFileName(FileName);
|
2008-04-07 14:06:35 +00:00
|
|
|
Result := hdr.Parse(parser);
|
|
|
|
if not Result then begin
|
|
|
|
if parser.Errors.Count > 0 then Err := parser.Errors[0]
|
|
|
|
else Err := 'undesribed error';
|
|
|
|
|
|
|
|
Err := Err + #13#10;
|
|
|
|
cnt := 120;
|
|
|
|
i := parser.Index - cnt;
|
|
|
|
if i <= 0 then begin
|
|
|
|
i := 1;
|
|
|
|
cnt := parser.Index;
|
|
|
|
end;
|
|
|
|
Err := Err + Copy(parser.Buf, i, cnt);
|
|
|
|
end;
|
|
|
|
|
2008-03-04 23:34:41 +00:00
|
|
|
except
|
|
|
|
end;
|
2008-03-25 08:17:24 +00:00
|
|
|
WriteOutIncludeFile(hdr, outdata);
|
2008-03-04 23:34:41 +00:00
|
|
|
finally
|
2008-03-28 10:25:55 +00:00
|
|
|
parser.TokenTable.Free;
|
|
|
|
parser.Free;
|
2008-03-27 15:27:00 +00:00
|
|
|
prec.Free;
|
2008-04-02 14:23:02 +00:00
|
|
|
//FreeEntity(hdr);
|
2008-03-04 23:34:41 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2008-04-02 14:23:02 +00:00
|
|
|
procedure ParseAll;
|
|
|
|
var
|
|
|
|
ch : char;
|
|
|
|
srch : TSearchRec;
|
|
|
|
res : Integer;
|
|
|
|
i : Integer;
|
|
|
|
pth : AnsiString;
|
|
|
|
incs : AnsiString;
|
|
|
|
st : TStringList;
|
|
|
|
f : Text;
|
2008-04-07 14:06:35 +00:00
|
|
|
err : AnsiString;
|
2008-04-02 14:23:02 +00:00
|
|
|
begin
|
2008-04-17 13:58:59 +00:00
|
|
|
err := '';
|
2008-04-07 14:06:35 +00:00
|
|
|
writeln('would you like to parse all current directory files .h to inc?');
|
2008-04-02 14:23:02 +00:00
|
|
|
readln(ch);
|
|
|
|
if (ch <> 'Y') and (ch <> 'y') then begin
|
|
|
|
writeln('as you wish, bye!');
|
|
|
|
Exit;
|
|
|
|
end;
|
2008-04-07 14:06:35 +00:00
|
|
|
|
2008-04-02 14:23:02 +00:00
|
|
|
pth := IncludeTrailingPathDelimiter( GetCurrentDir);
|
|
|
|
writeln('looking for .h files in ', pth);
|
|
|
|
res := FindFirst(pth + '*.h', -1, srch);
|
|
|
|
if res = 0 then begin
|
|
|
|
st := TStringList.Create;
|
|
|
|
try
|
|
|
|
repeat
|
|
|
|
write('found: ', srch.Name);
|
|
|
|
write(' parsing...');
|
|
|
|
//writeln('parsing: ', pth+srch.Name);
|
2008-04-07 14:06:35 +00:00
|
|
|
if ReadAndParseFile(pth+srch.Name, st, err) then begin
|
|
|
|
write(' parsed ');
|
|
|
|
incs := pth + Copy(srch.Name,1, length(srch.Name) - length(ExtractFileExt(srch.Name)));
|
|
|
|
incs := incs + '.inc';
|
|
|
|
//writeln(incs);
|
|
|
|
assignfile(f, incs); rewrite(f);
|
|
|
|
try
|
|
|
|
for i := 0 to st.Count - 1 do
|
|
|
|
writeln(f, st[i]);
|
|
|
|
finally
|
|
|
|
closefile(f);
|
|
|
|
end;
|
|
|
|
st.Clear;
|
|
|
|
writeln(' converted!');
|
|
|
|
end else begin
|
|
|
|
writeln('Error: ', err);
|
2008-04-08 09:22:54 +00:00
|
|
|
readln;
|
2008-04-02 14:23:02 +00:00
|
|
|
end;
|
|
|
|
until FindNext(srch) <> 0;
|
|
|
|
|
|
|
|
finally
|
|
|
|
FindClose(srch);
|
|
|
|
st.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2008-04-08 09:22:54 +00:00
|
|
|
const
|
|
|
|
ParamKey = '-';
|
|
|
|
|
|
|
|
function isParamValue(const s: AnsiString; var ParName, ParValue: AnsiString): Boolean;
|
|
|
|
var
|
|
|
|
i : Integer;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
if s = '' then Exit;
|
|
|
|
Result := (s[1] = ParamKey);
|
|
|
|
if not Result then Exit;
|
|
|
|
i := 1;
|
|
|
|
ScanWhile(s, i, [ParamKey]);
|
|
|
|
ParName := ScanTo(s, i, [#32, #9, '=']);
|
|
|
|
ScanWhile(s, i, [#32, #9, '=']);
|
|
|
|
ParValue := Copy(s, i, length(s) - i + 1);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure AddSpaceSeparated(const s: AnsiString; Strings: TStringList);
|
|
|
|
var
|
|
|
|
i : Integer;
|
|
|
|
ns : AnsiString;
|
|
|
|
begin
|
|
|
|
i := 1;
|
|
|
|
while i <= length(s) do begin
|
|
|
|
ScanTo(s, i, ['A'..'Z', 'a'..'z']);
|
|
|
|
ns := ScanTo(s, i, [#32, #9, '"']);
|
|
|
|
if ns <> '' then Strings.Add(ns);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function GetConvertSettings(Settings : TConvertSettings; var FileName: AnsiString): Boolean;
|
|
|
|
var
|
|
|
|
i : integer;
|
|
|
|
prm : AnsiString;
|
|
|
|
vlm : AnsiString;
|
|
|
|
Params : TStringList;
|
|
|
|
begin
|
2008-04-17 13:58:59 +00:00
|
|
|
prm := '';
|
|
|
|
vlm := '';
|
2008-04-08 09:22:54 +00:00
|
|
|
Params := TStringList.Create;
|
|
|
|
Params.CaseSensitive := false;
|
|
|
|
try
|
|
|
|
for i := 1 to ParamCount do begin
|
|
|
|
if isParamValue(ParamStr(i), prm, vlm) then begin
|
|
|
|
prm := AnsiLowerCase(prm);
|
|
|
|
if prm = 'mu' then prm := 'mainunit'
|
|
|
|
else if prm = 'ii' then prm := 'ignoreinclude';
|
|
|
|
Params.Values[prm] := vlm;
|
|
|
|
end else
|
|
|
|
FileName := ParamStr(i);
|
|
|
|
end;
|
|
|
|
|
|
|
|
vlm := Params.Values['mainunit'];
|
|
|
|
if vlm <> '' then
|
|
|
|
Settings.ConvertPrefix.Add ('{%mainunit '+vlm+'}');
|
|
|
|
|
|
|
|
vlm := Params.Values['ignoreinclude'];
|
|
|
|
if vlm <> '' then begin
|
|
|
|
AddSpaceSeparated(vlm, Settings.IgnoreIncludes);
|
2008-04-08 10:45:08 +00:00
|
|
|
{for i := 0 to Settings.IgnoreIncludes.Count - 1 do begin
|
2008-04-08 09:22:54 +00:00
|
|
|
vlm := Settings.IgnoreIncludes[i];
|
|
|
|
vlm := Copy(vlm, 1, length(vlm) - length(ExtractFileExt(vlm)));
|
|
|
|
vlm := vlm + '.inc';
|
|
|
|
Settings.IgnoreIncludes[i] := vlm;
|
2008-04-08 10:45:08 +00:00
|
|
|
end;}
|
2008-04-08 09:22:54 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
finally
|
|
|
|
Params.Free;
|
|
|
|
end;
|
|
|
|
Result := true;
|
|
|
|
end;
|
2008-04-02 14:23:02 +00:00
|
|
|
|
2008-03-04 23:34:41 +00:00
|
|
|
var
|
2008-04-17 13:58:59 +00:00
|
|
|
inpf : AnsiString = '';
|
|
|
|
st : TStrings = nil;
|
2008-03-31 12:39:54 +00:00
|
|
|
i : integer;
|
2008-04-17 13:58:59 +00:00
|
|
|
err : AnsiString = '';
|
2008-03-04 23:34:41 +00:00
|
|
|
begin
|
|
|
|
try
|
2008-04-08 09:22:54 +00:00
|
|
|
GetConvertSettings(ConvertSettings, inpf);
|
2008-03-31 12:39:54 +00:00
|
|
|
if not FileExists(inpf) then begin
|
2008-04-15 14:13:34 +00:00
|
|
|
ParseAll;
|
2008-03-31 12:39:54 +00:00
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
st := TStringList.Create;
|
|
|
|
try
|
2008-04-08 09:22:54 +00:00
|
|
|
if not ReadAndParseFile(inpf, st, err) then
|
2008-04-07 14:06:35 +00:00
|
|
|
writeln('Error: ', err)
|
|
|
|
else
|
|
|
|
for i := 0 to st.Count - 1 do
|
|
|
|
writeln(st[i]);
|
2008-03-31 12:39:54 +00:00
|
|
|
except
|
|
|
|
end;
|
|
|
|
st.Free;
|
2008-03-25 08:17:24 +00:00
|
|
|
except
|
2008-03-31 12:39:54 +00:00
|
|
|
on e: exception do
|
|
|
|
writeln(e.Message);
|
2008-03-04 23:34:41 +00:00
|
|
|
end;
|
|
|
|
end.
|
|
|
|
|