Browse Source

* Fix TPasWriter so it produces compileable output, add more constructs. Sample program to rewrite a source file

git-svn-id: trunk@37103 -
michael 8 years ago
parent
commit
0415de90e7

+ 2 - 0
.gitattributes

@@ -2600,6 +2600,8 @@ packages/fcl-passrc/Makefile svneol=native#text/plain
 packages/fcl-passrc/Makefile.fpc svneol=native#text/plain
 packages/fcl-passrc/Makefile.fpc svneol=native#text/plain
 packages/fcl-passrc/Makefile.fpc.fpcmake svneol=native#text/plain
 packages/fcl-passrc/Makefile.fpc.fpcmake svneol=native#text/plain
 packages/fcl-passrc/examples/parsepp.pp svneol=native#text/plain
 packages/fcl-passrc/examples/parsepp.pp svneol=native#text/plain
+packages/fcl-passrc/examples/pasrewrite.lpi svneol=native#text/plain
+packages/fcl-passrc/examples/pasrewrite.pp svneol=native#text/plain
 packages/fcl-passrc/examples/test_parser.pp svneol=native#text/plain
 packages/fcl-passrc/examples/test_parser.pp svneol=native#text/plain
 packages/fcl-passrc/examples/testunit1.pp svneol=native#text/plain
 packages/fcl-passrc/examples/testunit1.pp svneol=native#text/plain
 packages/fcl-passrc/fpmake.pp svneol=native#text/plain
 packages/fcl-passrc/fpmake.pp svneol=native#text/plain

+ 62 - 0
packages/fcl-passrc/examples/pasrewrite.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="pasrewrite"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="--input=&quot;$HOME/source/pas2js/src/rtl/web.pas -S2h&quot; --no-externalclass --no-implementation --no-externalvar --no-externalfunction -x jstypes -o web.pp"/>
+      </local>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="pasrewrite.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="pasrewrite"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="../src"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 482 - 0
packages/fcl-passrc/examples/pasrewrite.pp

@@ -0,0 +1,482 @@
+program pasrewrite;
+
+{$mode objfpc}
+{$H+}
+
+uses SysUtils, inifiles, strutils, Classes, Pscanner,PParser, PasTree, paswrite, custapp, iostream;
+
+//# types the parser needs
+
+type
+  { We have to override abstract TPasTreeContainer methods.
+    See utils/fpdoc/dglobals.pp for an implementation of TFPDocEngine,
+    a "real" engine. }
+  TSimpleEngine = class(TPasTreeContainer)
+  public
+    function CreateElement(AClass: TPTreeElement; const AName: String;
+      AParent: TPasElement; AVisibility: TPasMemberVisibility;
+      const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
+      override;
+    function FindElement(const AName: String): TPasElement; override;
+  end;
+
+  { TPasRewriteApplication }
+
+  TPasRewriteApplication  = Class(TCustomApplication)
+  Private
+    FHeaderFile : String;
+    FDefines : TStrings;
+    FLineNumberWidth,
+    FIndentSize : Integer;
+    FOptions : TPasWriterOptions;
+    FForwardClasses,
+    FExtraUnits,
+    cmdl,
+    ConfigFile,
+    filename,
+    TargetOS,
+    TargetCPU : string;
+    function GetModule: TPasModule;
+    procedure PrintUsage(S: String);
+    procedure ReadConfig(const aFileName: String);
+    procedure ReadConfig(const aIni: TIniFile);
+    procedure WriteModule(M: TPasModule);
+  Protected
+    function ParseOptions : Boolean;
+    Procedure DoRun; override;
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    Destructor Destroy; override;
+  end;
+
+{ TSimpleEngine }
+
+function TSimpleEngine.CreateElement(AClass: TPTreeElement; const AName: String;
+  AParent: TPasElement; AVisibility: TPasMemberVisibility;
+  const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
+begin
+  Result := AClass.Create(AName, AParent);
+  Result.Visibility := AVisibility;
+  Result.SourceFilename := ASourceFilename;
+  Result.SourceLinenumber := ASourceLinenumber;
+end;
+
+function TSimpleEngine.FindElement(const AName: String): TPasElement;
+begin
+  { dummy implementation, see TFPDocEngine.FindElement for a real example }
+  Result := nil;
+end;
+
+{ TPasRewriteApplication }
+
+procedure TPasRewriteApplication.PrintUsage(S : String);
+
+begin
+  if S<>'' then
+    Writeln('Error : ',S);
+  writeln('usage: pasrewrite options');
+  writeln;
+  writeln('Where options is one or more of');
+  writeln('-s --os=OS            Set OS, one of WINDOWS, LINUX (default), FREEBSD, NETBSD,');
+  writeln('                           SUNOS, BEOS, QNX, GO32V2');
+  writeln('-u --cpu=CPU          Set CPU = i386 (default), x86_64');
+  writeln('-x --extra=units      Comma-separated list of extra units to be added to uses list.');
+  writeln('-i --input=cmd        Is the commandline for the parser');
+  writeln('-o --output=file      Output file name. If not specified, standard output is assumed ');
+  Writeln('-t --indent=N         Number of characters for indent (default 2)');
+  Writeln('-c --config=filename  Read ini file with configuration');
+  Writeln('-H --header=filename  Add file header using contents of file "filename"');
+  Writeln('--no-implementation   Skip generation of executeable code');
+  Writeln('--no-externalclass    Skip generation of external classes (write as regular class)');
+  Writeln('--no-externalvar      Skip generation of external variables (write as regular variables)');
+  Writeln('--no-externalfunction Skip generation of external functions (write as regular functions)');
+  Writeln('-f --forwardclasses[=list]');
+  Writeln('                      Generate forward definitions for list of classes. If empty, for all classes.');
+  Writeln('-n --add-linenumber   Add linenumber to comment in front of each line');
+  Writeln('-N --add-sourcelinenumber   Add source linenumber to comment in front of each line');
+  Writeln('-w --linenumberwidth  Number of digits to pad line numbers (default 4)');
+  ExitCode:=Ord(S<>'');
+end;
+
+function TPasRewriteApplication.ParseOptions : Boolean;
+
+Var
+  S : String;
+
+begin
+  TargetOS:='linux';
+  TargetCPU:='i386';
+  FIndentSize:=-1;
+  FOptions:=[];
+  Result:=False;
+  S:=CheckOptions('d:w:fhs:u:i:o:nNt:c:x:',['help','os:','cpu:','input:','output:','indent:','define',
+                                    'no-implementation','no-externalclass',
+                                    'no-externalvar','add-linenumber','add-sourcelinenumber',
+                                    'no-externalfunction','extra:','forwardclasses::',
+                                    'config:','linenumberwidth']);
+  if (S<>'') or HasOption('h','help') then
+     begin
+     PrintUsage(S);
+     Exit;
+     end;
+  // Standard options
+  cmdl:=GetOptionValue('i','input');
+  FileName:=GetOptionValue('o','output');
+  FHeaderFile:=GetOptionValue('H','header');;
+  if HasOption('s','os') then
+    TargetOS:=GetOPtionValue('s','os');
+  if HasOption('u','cpu') then
+    TargetCPU:=GetOptionValue('u','cpu');
+  ConfigFile:=GetOptionValue('c','config');
+  FExtraUnits:=GetOptionValue('x','extra');
+  // Options
+  if Hasoption('w','linenumberwidth') then
+    FLineNumberWidth:=StrToIntDef(GetOptionValue('w','linenumberwidth'),-1);
+  if Hasoption('n','add-linenumber') then
+    Include(Foptions,woAddLineNumber);
+  if Hasoption('N','add-sourcelinenumber') then
+    Include(Foptions,woAddSourceLineNumber);
+  if Hasoption('no-implementation') then
+    Include(Foptions,woNoImplementation);
+  if Hasoption('no-externalclass') then
+    Include(Foptions,woNoExternalClass);
+  if Hasoption('no-externalvar') then
+    Include(Foptions,woNoExternalVar);
+  if Hasoption('no-externalfunction') then
+    Include(Foptions,woNoExternalFunc);
+  If HasOption('d','define') then
+    for S in GetOptionValues('d','define') do
+      FDefines.Add(S);
+  if Hasoption('f','forwardclasses') then
+    begin
+    Include(Foptions,woForwardClasses);
+    FForwardClasses:=GetOptionValue('f','forwardclasses');
+    end;
+  // Indent
+  if HasOption('t','indent') then
+    FIndentSize:=StrToIntDef(GetOptionValue('d','indent'),-1);
+  if (FHeaderFile<>'') and Not FileExists(FheaderFile) then
+    begin
+    PrintUsage(Format('Header file "%s"does not exist',[FHeaderFile]));
+    Exit;
+    end;
+  //  Check options
+  Result:=(Cmdl<>'') ;
+  If Not Result then
+    PrintUsage('Need input');
+end;
+
+{ TPasRewriteApplication }
+
+
+
+Function TPasRewriteApplication.GetModule : TPasModule;
+
+Var
+  SE : TSimpleEngine;
+  FileResolver: TFileResolver;
+  InputFileName : string;
+  Parser: TPasParser;
+  Start, CurPos: PChar;
+  Scanner: TPascalScanner;
+
+  procedure ProcessCmdLinePart;
+
+  var
+    l: Integer;
+    s: String;
+  begin
+    l := CurPos - Start;
+    SetLength(s, l);
+    if l > 0 then
+      Move(Start^, s[1], l)
+    else
+      exit;
+    if (s[1] = '-') and (length(s)>1) then
+    begin
+      case s[2] of
+        'd': // -d define
+          Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
+        'u': // -u undefine
+          Scanner.RemoveDefine(UpperCase(Copy(s, 3, Length(s))));
+        'F': // -F
+          if (length(s)>2) and (s[3] = 'i') then // -Fi include path
+            FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
+        'I': // -I include path
+          FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
+        'S': // -S mode
+          if  (length(s)>2) then
+            begin
+            l:=3;
+            While L<=Length(S) do
+              begin
+              case S[l] of
+                'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
+                'd' : Scanner.SetCompilerMode('DELPHI');
+                '2' : Scanner.SetCompilerMode('OBJFPC');
+                'h' : ; // do nothing
+              end;
+              inc(l);
+              end;
+            end;
+        'M' :
+           begin
+           delete(S,1,2);
+           Scanner.SetCompilerMode(S);
+           end;
+      end;
+    end else
+      if InputFilename <> '' then
+        raise Exception.Create(SErrMultipleSourceFiles)
+      else
+        InputFilename := s;
+  end;
+
+
+var
+  s: String;
+
+begin
+  try
+    Result := nil;
+    FileResolver := nil;
+    Scanner := nil;
+    Parser := nil;
+    SE:=TSimpleEngine.Create;
+    try
+      FileResolver := TFileResolver.Create;
+      FileResolver.UseStreams:=True;
+      Scanner := TPascalScanner.Create(FileResolver);
+      Scanner.Options:=[po_AsmWhole];
+      SCanner.LogEvents:=SE.ScannerLogEvents;
+      SCanner.OnLog:=SE.Onlog;
+      Scanner.AddDefine('FPK');
+      Scanner.AddDefine('FPC');
+      For S in FDefines do
+        Scanner.AddDefine(S);
+      // TargetOS
+      s := UpperCase(TargetOS);
+      Scanner.AddDefine(s);
+      if s = 'LINUX' then
+        Scanner.AddDefine('UNIX')
+      else if s = 'FREEBSD' then
+      begin
+        Scanner.AddDefine('BSD');
+        Scanner.AddDefine('UNIX');
+      end else if s = 'NETBSD' then
+      begin
+        Scanner.AddDefine('BSD');
+        Scanner.AddDefine('UNIX');
+      end else if s = 'SUNOS' then
+      begin
+        Scanner.AddDefine('SOLARIS');
+        Scanner.AddDefine('UNIX');
+      end else if s = 'GO32V2' then
+        Scanner.AddDefine('DPMI')
+      else if s = 'BEOS' then
+        Scanner.AddDefine('UNIX')
+      else if s = 'QNX' then
+        Scanner.AddDefine('UNIX')
+      else if s = 'AROS' then
+        Scanner.AddDefine('HASAMIGA')
+      else if s = 'MORPHOS' then
+        Scanner.AddDefine('HASAMIGA')
+      else if s = 'AMIGA' then
+        Scanner.AddDefine('HASAMIGA');
+
+      // TargetCPU
+      s := UpperCase(TargetCPU);
+      Scanner.AddDefine('CPU'+s);
+      if (s='X86_64') then
+        Scanner.AddDefine('CPU64')
+      else
+        Scanner.AddDefine('CPU32');
+      Parser := TPasParser.Create(Scanner, FileResolver, SE);
+      InputFilename := '';
+      Parser.LogEvents:=SE.ParserLogEvents;
+      Parser.OnLog:=SE.Onlog;
+
+      if cmdl<>'' then
+        begin
+          Start := @cmdl[1];
+          CurPos := Start;
+          while CurPos[0] <> #0 do
+          begin
+            if CurPos[0] = ' ' then
+            begin
+              ProcessCmdLinePart;
+              Start := CurPos + 1;
+            end;
+            Inc(CurPos);
+          end;
+          ProcessCmdLinePart;
+        end;
+
+      if InputFilename = '' then
+        raise Exception.Create(SErrNoSourceGiven);
+      FileResolver.AddIncludePath(ExtractFilePath(InputFileName));
+      Scanner.OpenFile(InputFilename);
+      Parser.Options:=Parser.Options+[po_AsmWhole];
+      Parser.ParseMain(Result);
+    finally
+      Parser.Free;
+      Scanner.Free;
+      FileResolver.Free;
+      SE.Free;
+    end;
+  except
+    on E : EParserError do
+      begin
+      writeln(E.message,' line:',E .row,' column:', E .column,' file:',E.filename);
+      end;
+    on Ex : Exception do
+      begin
+      Writeln(Ex.Message);
+      end;
+  end;
+end;
+
+procedure TPasRewriteApplication.ReadConfig(const aFileName: String);
+
+Var
+  ini : TMemIniFile;
+
+begin
+  ini:=TMemIniFile.Create(AFileName);
+  try
+    ReadConfig(Ini);
+  finally
+    Ini.Free;
+  end;
+end;
+
+procedure TPasRewriteApplication.ReadConfig(const aIni: TIniFile);
+
+Const
+  DelChars = [',',' '];
+
+Var
+  O : TPaswriterOptions;
+  W,S : String;
+  I : Integer;
+
+
+begin
+  O:=[];
+  With aIni do
+    begin
+    TargetOS:=ReadString('config','targetos',TargetOS);
+    TargetCPU:=ReadString('config','targetcpu',TargetCPU);
+    S:=ReadString('config','options','');
+    if (S<>'') then
+      For I:=1 to WordCount(S,DelChars) do
+        begin
+        W:=LowerCase(ExtractWord(I,S,DelChars));
+        Case w of
+         'noimplementation': Include(O,woNoImplementation);
+         'noexternalclass' : Include(O,woNoExternalClass);
+         'noexternalvar' : Include(O,woNoExternalVar);
+         'noexternalfunction' : Include(O,woNoExternalFunc);
+         'forwardclasses' : Include(O,woForwardClasses);
+         'addlinenumber': Include(O,woAddLineNumber);
+         'addsourcelinenumber': Include(O,woAddSourceLineNumber);
+        end;
+        end;
+    FOptions:=O;
+    cmdl:=ReadString('config','input',cmdl);
+    Self.filename:=ReadString('config','output',Self.filename);
+    FIndentSize:=ReadInteger('config','indentsize',FIndentSize);
+    FLineNumberWidth:=ReadInteger('config','linenumberwidth',FLineNumberWidth);
+    FExtraUnits:=ReadString('config','extra',FExtraUnits);
+    FForwardClasses:=ReadString('config','forwardclasses',FForwardClasses);
+    S:=ReadString('config','defines','');
+    if (S<>'') then
+      For I:=1 to WordCount(S,DelChars) do
+        FDefines.Add(UpperCase(ExtractWord(I,S,DelChars)));
+    if (FForwardClasses<>'') then
+      Include(O,woForwardClasses);
+    end;
+end;
+
+procedure TPasRewriteApplication.WriteModule(M : TPAsModule);
+
+Var
+  F,H : TStream;
+  W : TPasWriter;
+
+begin
+  W:=Nil;
+  if FileName='' then
+    F:=TIOStream.Create(iosOutPut)
+  else
+    F:=TFileStream.Create(FileName,fmCreate);
+  try
+     if (FHeaderFile<>'') then
+       begin
+       H:=TFileStream.Create(FHeaderFile,fmOpenRead or fmShareDenyWrite);
+       try
+         F.CopyFrom(H,H.Size);
+       finally
+         H.Free;
+       end;
+       end;
+     W:=TPasWriter.Create(F);
+     W.Options:=FOptions;
+     W.ExtraUnits:=FExtraUnits;
+     if FIndentSize<>-1 then
+       W.IndentSize:=FIndentSize;
+     if FLineNumberWidth>0 then
+       W.LineNumberWidth:=FLineNumberWidth;
+     W.ForwardClasses.CommaText:=FForwardClasses;
+     W.WriteModule(M);
+  finally
+    W.Free;
+    F.Free;
+  end;
+end;
+
+procedure TPasRewriteApplication.DoRun;
+
+Var
+  M: TPasModule;
+
+begin
+  Terminate;
+  TargetOS:='linux';
+  TargetCPU:='i386';
+  If not ParseOptions then
+    exit;
+  If (ConfigFile<>'') then
+    ReadConfig(ConfigFile);
+  M:=GetModule;
+  if M=Nil then
+    exit;
+  try
+    WriteModule(M);
+  finally
+    M.Free;
+  end;
+end;
+
+constructor TPasRewriteApplication.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FDefines:=TStringList.Create;
+
+end;
+
+destructor TPasRewriteApplication.Destroy;
+begin
+  FreeAndNil(FDefines);
+  inherited Destroy;
+end;
+
+Var
+  Application : TPasRewriteApplication;
+
+begin
+  Application:=TPasRewriteApplication.Create(Nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.

+ 32 - 27
packages/fcl-passrc/src/pastree.pp

@@ -456,6 +456,8 @@ type
   { TPasType }
   { TPasType }
 
 
   TPasType = class(TPasElement)
   TPasType = class(TPasElement)
+  Protected
+    Function FixTypeDecl(aDecl: String) : String;
   public
   public
     function ElementTypeName: string; override;
     function ElementTypeName: string; override;
   end;
   end;
@@ -1921,6 +1923,15 @@ begin
 end;
 end;
 
 
 function TPasResString.ElementTypeName: string; begin Result := SPasTreeResString; end;
 function TPasResString.ElementTypeName: string; begin Result := SPasTreeResString; end;
+
+function TPasType.FixTypeDecl(aDecl: String): String;
+begin
+  Result:=aDecl;
+  if (Name<>'') then
+    Result:=Name+' = '+Result;
+  ProcessHints(false,Result);
+end;
+
 function TPasType.ElementTypeName: string; begin Result := SPasTreeType; end;
 function TPasType.ElementTypeName: string; begin Result := SPasTreeType; end;
 function TPasPointerType.ElementTypeName: string; begin Result := SPasTreePointerType; end;
 function TPasPointerType.ElementTypeName: string; begin Result := SPasTreePointerType; end;
 function TPasAliasType.ElementTypeName: string; begin Result := SPasTreeAliasType; end;
 function TPasAliasType.ElementTypeName: string; begin Result := SPasTreeAliasType; end;
@@ -3311,10 +3322,7 @@ function TPasAliasType.GetDeclaration(full: Boolean): string;
 begin
 begin
   Result:=DestType.Name;
   Result:=DestType.Name;
   If Full then
   If Full then
-    begin
-    Result:=Name+' = '+Result;
-    ProcessHints(False,Result);
-    end;
+    Result:=FixTypeDecl(Result);
 end;
 end;
 
 
 procedure TPasAliasType.ForEachCall(const aMethodCall: TOnForEachPasElement;
 procedure TPasAliasType.ForEachCall(const aMethodCall: TOnForEachPasElement;
@@ -3328,20 +3336,14 @@ function TPasClassOfType.GetDeclaration (full : boolean) : string;
 begin
 begin
   Result:='Class of '+DestType.Name;
   Result:='Class of '+DestType.Name;
   If Full then
   If Full then
-    begin
-    Result:=Name+' = '+Result;
-    ProcessHints(False,Result);
-    end;
+    Result:=FixTypeDecl(Result);
 end;
 end;
 
 
 function TPasRangeType.GetDeclaration (full : boolean) : string;
 function TPasRangeType.GetDeclaration (full : boolean) : string;
 begin
 begin
   Result:=RangeStart+'..'+RangeEnd;
   Result:=RangeStart+'..'+RangeEnd;
   If Full then
   If Full then
-    begin
-    Result:=Name+' = '+Result;
-    ProcessHints(False,Result);
-    end;
+    Result:=FixTypeDecl(Result);
 end;
 end;
 
 
 procedure TPasRangeType.ForEachCall(const aMethodCall: TOnForEachPasElement;
 procedure TPasRangeType.ForEachCall(const aMethodCall: TOnForEachPasElement;
@@ -3380,10 +3382,7 @@ begin
   else
   else
     Result:=Result+'const';
     Result:=Result+'const';
   If Full Then
   If Full Then
-    begin
-    Result:=Name+' = '+Result;
-    ProcessHints(False,Result);
-    end;
+    Result:=FixTypeDecl(Result);
 end;
 end;
 
 
 procedure TPasArrayType.ForEachCall(const aMethodCall: TOnForEachPasElement;
 procedure TPasArrayType.ForEachCall(const aMethodCall: TOnForEachPasElement;
@@ -3418,10 +3417,7 @@ begin
   If Assigned(Eltype) then
   If Assigned(Eltype) then
     Result:=Result+' of '+ElType.Name;
     Result:=Result+' of '+ElType.Name;
   If Full Then
   If Full Then
-    begin
-    Result:=Name+' = '+Result;
-    ProcessHints(False,Result);
-    end;
+    Result:=FixTypeDecl(Result);
 end;
 end;
 
 
 procedure TPasFileType.ForEachCall(const aMethodCall: TOnForEachPasElement;
 procedure TPasFileType.ForEachCall(const aMethodCall: TOnForEachPasElement;
@@ -3462,7 +3458,7 @@ Var
 begin
 begin
   S:=TStringList.Create;
   S:=TStringList.Create;
   Try
   Try
-    If Full then
+    If Full and (Name<>'') then
       S.Add(Name+' = (')
       S.Add(Name+' = (')
     else
     else
       S.Add('(');
       S.Add('(');
@@ -3496,7 +3492,7 @@ begin
     begin
     begin
     S:=TStringList.Create;
     S:=TStringList.Create;
     Try
     Try
-      If Full then
+      If Full and (Name<>'') then
         S.Add(Name+'= Set of (')
         S.Add(Name+'= Set of (')
       else
       else
         S.Add('Set of (');
         S.Add('Set of (');
@@ -3586,6 +3582,7 @@ function TPasRecordType.GetDeclaration (full : boolean) : string;
 Var
 Var
   S : TStringList;
   S : TStringList;
   temp : string;
   temp : string;
+  i : integer;
 
 
 begin
 begin
   S:=TStringList.Create;
   S:=TStringList.Create;
@@ -3596,13 +3593,14 @@ begin
         Temp:='bitpacked '+Temp
         Temp:='bitpacked '+Temp
       else
       else
         Temp:='packed '+Temp;
         Temp:='packed '+Temp;
-    If Full then
+    If Full and (Name<>'') then
       Temp:=Name+' = '+Temp;
       Temp:=Name+' = '+Temp;
     S.Add(Temp);
     S.Add(Temp);
     GetMembers(S);
     GetMembers(S);
     S.Add('end');
     S.Add('end');
     Result:=S.Text;
     Result:=S.Text;
-    ProcessHints(False, Result);
+    if Full then
+      ProcessHints(False, Result);
   finally
   finally
     S.free;
     S.free;
   end;
   end;
@@ -4117,7 +4115,7 @@ begin
       Result:=ArgType.Name
       Result:=ArgType.Name
     else
     else
       Result:=ArgType.GetDeclaration(False);
       Result:=ArgType.GetDeclaration(False);
-    If Full then
+    If Full and (Name<>'') then
       Result:=Name+': '+Result;
       Result:=Name+': '+Result;
     end
     end
   else If Full then
   else If Full then
@@ -4573,10 +4571,15 @@ end;
 
 
 function TUnaryExpr.GetDeclaration(full: Boolean): string;
 function TUnaryExpr.GetDeclaration(full: Boolean): string;
 
 
+Const
+  WordOpcodes = [eopDiv,eopMod,eopshr,eopshl,eopNot,eopAnd,eopOr,eopXor];
+
 begin
 begin
   Result:=OpCodeStrings[Opcode];
   Result:=OpCodeStrings[Opcode];
+  if OpCode in WordOpCodes  then
+    Result:=Result+' ';
   If Assigned(Operand) then
   If Assigned(Operand) then
-    Result:=Result+Operand.GetDeclaration(Full);
+    Result:=Result+' '+Operand.GetDeclaration(Full);
 end;
 end;
 
 
 constructor TUnaryExpr.Create(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode);
 constructor TUnaryExpr.Create(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode);
@@ -4639,7 +4642,7 @@ begin
   If Assigned(Right) then
   If Assigned(Right) then
   begin
   begin
     op := Right.GetDeclaration(Full);
     op := Right.GetDeclaration(Full);
-    if (OpLevel(Right) < 5) and (OpLevel(Right) >= OpLevel(Self)) then
+    if OpLevel(Left) < OpLevel(Self) then
       Result := Result + '(' + op + ')'
       Result := Result + '(' + op + ')'
     else
     else
       Result := Result + op;
       Result := Result + op;
@@ -4701,6 +4704,8 @@ begin
     Result := '[' + Result + ']'
     Result := '[' + Result + ']'
   else
   else
     Result := '(' + Result + ')';
     Result := '(' + Result + ')';
+  if full and Assigned(Value) then
+    Result:=Value.GetDeclaration(True)+Result;
 end;
 end;
 
 
 procedure TParamsExpr.AddParam(xp:TPasExpr);
 procedure TParamsExpr.AddParam(xp:TPasExpr);

File diff suppressed because it is too large
+ 670 - 245
packages/fcl-passrc/src/paswrite.pp


Some files were not shown because too many files changed in this diff