Переглянути джерело

--- Merging r19621 into '.':
U packages/fcl-passrc/src/pastree.pp
U packages/fcl-passrc/src/pscanner.pp
U packages/fcl-passrc/src/pparser.pp
U packages/fcl-passrc/examples/test_parser.pp
U packages/fcl-passrc/examples/testunit1.pp
--- Merging r19622 into '.':
U utils/fpdoc/dw_html.pp
U utils/fpdoc/fpdoc.lpi
U utils/fpdoc/fpclasschart.pp
U utils/fpdoc/testunit.pp
U utils/fpdoc/fpdoc.pp
--- Merging r19623 into '.':
G packages/fcl-passrc/src/pastree.pp
--- Merging r19624 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Merging r19625 into '.':
U utils/fpdoc/dglobals.pp
--- Merging r19626 into '.':
U utils/fpdoc/dwlinear.pp
--- Merging r19662 into '.':
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pscanner.pp
G packages/fcl-passrc/src/pparser.pp
--- Merging r19663 into '.':
G packages/fcl-passrc/examples/test_parser.pp
G packages/fcl-passrc/examples/testunit1.pp
--- Merging r19664 into '.':
G packages/fcl-passrc/examples/testunit1.pp
--- Merging r19669 into '.':
G utils/fpdoc/dwlinear.pp
U utils/fpdoc/dw_man.pp
G utils/fpdoc/dglobals.pp
G utils/fpdoc/dw_html.pp
--- Merging r19670 into '.':
G utils/fpdoc/dw_html.pp
--- Merging r19724 into '.':
U utils/fpdoc/fpdocxmlopts.pas
G utils/fpdoc/dglobals.pp
G utils/fpdoc/fpdoc.lpi
G utils/fpdoc/fpdoc.pp
--- Merging r19725 into '.':
A utils/fpdoc/mkfpdocproj.pp
A utils/fpdoc/mkfpdocproj.lpi
--- Merging r19730 into '.':
G utils/fpdoc/fpdocxmlopts.pas
A utils/fpdoc/mgrfpdocproj.pp
U utils/fpdoc/mkfpdocproj.pp
U utils/fpdoc/mkfpdocproj.lpi
--- Merging r19735 into '.':
G utils/fpdoc/fpdocxmlopts.pas
U utils/fpdoc/mgrfpdocproj.pp
G utils/fpdoc/mkfpdocproj.pp
G utils/fpdoc/mkfpdocproj.lpi
--- Merging r19752 into '.':
G packages/fcl-passrc/src/pscanner.pp
G packages/fcl-passrc/src/pparser.pp
--- Merging r19753 into '.':
U utils/fpdoc/dwriter.pp
G utils/fpdoc/dglobals.pp
G utils/fpdoc/dw_html.pp
G utils/fpdoc/fpdoc.lpi
A utils/fpdoc/mkfpdoc.pp
G utils/fpdoc/fpdoc.pp
--- Merging r19755 into '.':
G utils/fpdoc/dglobals.pp
G utils/fpdoc/fpdoc.pp
--- Merging r19761 into '.':
G utils/fpdoc/fpdocxmlopts.pas
G utils/fpdoc/mgrfpdocproj.pp
G utils/fpdoc/mkfpdocproj.pp
--- Merging r19776 into '.':
G utils/fpdoc/mkfpdocproj.pp
--- Merging r19786 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Merging r19795 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Merging r19796 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Merging r19797 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Merging r19798 into '.':
A packages/fcl-passrc/tests
A packages/fcl-passrc/tests/tcscanner.pas
A packages/fcl-passrc/tests/testpassrc.lpr
A packages/fcl-passrc/tests/testpassrc.lpi
--- Merging r19850 into '.':
U utils/fpdoc/unitdiff.pp
--- Merging r19884 into '.':
G utils/fpdoc/dglobals.pp
G utils/fpdoc/fpdoc.pp
--- Merging r19901 into '.':
U utils/fpdoc/Makefile.fpc
G utils/fpdoc/dwriter.pp
G utils/fpdoc/dw_html.pp
C utils/fpdoc/Makefile
--- Merging r19903 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Merging r19951 into '.':
U utils/fpcm/fpcmake.ini
C utils/fpcm/fpcmake.inc
C packages/fcl-extra/Makefile
C packages/fcl-net/Makefile
C packages/fcl-res/Makefile
C packages/fcl-passrc/Makefile
C packages/fcl-registry/Makefile
C packages/fastcgi/Makefile
C packages/fcl-image/Makefile
C packages/fcl-web/Makefile
C packages/fcl-base/Makefile
C packages/fcl-async/Makefile
C packages/fcl-json/Makefile
C packages/fcl-js/Makefile
--- Merging r19993 into '.':
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pparser.pp
--- Merging r19996 into '.':
U packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
--- Merging r19997 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
--- Merging r20005 into '.':
U utils/fpdoc/dw_dxml.pp
--- Merging r20009 into '.':
G utils/fpdoc/dw_html.pp
--- Merging r20011 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Merging r20012 into '.':
G packages/fcl-passrc/src/pastree.pp
--- Merging r20013 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Merging r20014 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
Summary of conflicts:
Text conflicts: 14

# revisions: 19621,19622,19623,19624,19625,19626,19662,19663,19664,19669,19670,19724,19725,19730,19735,19752,19753,19755,19761,19776,19786,19795,19796,19797,19798,19850,19884,19901,19903,19951,19993,19996,19997,20005,20009,20011,20012,20013,20014
r19621 | michael | 2011-11-11 16:08:17 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/examples/test_parser.pp
M /trunk/packages/fcl-passrc/examples/testunit1.pp
M /trunk/packages/fcl-passrc/src/pastree.pp
M /trunk/packages/fcl-passrc/src/pparser.pp
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Support for generics
r19622 | michael | 2011-11-11 16:08:42 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dw_html.pp
M /trunk/utils/fpdoc/fpclasschart.pp
M /trunk/utils/fpdoc/fpdoc.lpi
M /trunk/utils/fpdoc/fpdoc.pp
M /trunk/utils/fpdoc/testunit.pp

* Support for generics
r19623 | michael | 2011-11-11 18:14:38 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pastree.pp

* Set declaration returns type of name if named enumeration
r19624 | michael | 2011-11-11 18:17:35 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp

* Fixed some indentation
r19625 | michael | 2011-11-11 18:17:58 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp

* Removed debug statement
r19626 | michael | 2011-11-11 18:18:21 +0100 (Fri, 11 Nov 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dwlinear.pp

* Output table with enumerated explanations for set
r19662 | michael | 2011-11-20 23:46:54 +0100 (Sun, 20 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pastree.pp
M /trunk/packages/fcl-passrc/src/pparser.pp
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Refactoring in preparation of extended features (nested type, extended records) support
r19663 | michael | 2011-11-20 23:48:29 +0100 (Sun, 20 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/examples/test_parser.pp
M /trunk/packages/fcl-passrc/examples/testunit1.pp

* More extensive examples taken from RTL
r19664 | michael | 2011-11-20 23:49:14 +0100 (Sun, 20 Nov 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/examples/testunit1.pp

* Uncommented some extra tests
r19669 | michael | 2011-11-22 19:15:28 +0100 (Tue, 22 Nov 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp
M /trunk/utils/fpdoc/dw_html.pp
M /trunk/utils/fpdoc/dw_man.pp
M /trunk/utils/fpdoc/dwlinear.pp

* TList -> TFPList to match latest changes in fcl-passrc
r19670 | michael | 2011-11-22 20:21:20 +0100 (Tue, 22 Nov 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dw_html.pp

* Missing conversion to TFPList
r19724 | michael | 2011-12-02 17:24:29 +0100 (Fri, 02 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp
M /trunk/utils/fpdoc/fpdoc.lpi
M /trunk/utils/fpdoc/fpdoc.pp
M /trunk/utils/fpdoc/fpdocxmlopts.pas

* Implemented project file writing functionality, based on patch from Hans-Peter Diettrich
r19725 | michael | 2011-12-02 19:44:58 +0100 (Fri, 02 Dec 2011) | 1 line
Changed paths:
A /trunk/utils/fpdoc/mkfpdocproj.lpi
A /trunk/utils/fpdoc/mkfpdocproj.pp

* Start of project file manipulation program
r19730 | michael | 2011-12-03 01:26:20 +0100 (Sat, 03 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/fpdocxmlopts.pas
A /trunk/utils/fpdoc/mgrfpdocproj.pp
M /trunk/utils/fpdoc/mkfpdocproj.lpi
M /trunk/utils/fpdoc/mkfpdocproj.pp

* Added lots of commands to fpdoc file manager, moved to separate class and unit for reuse
r19735 | michael | 2011-12-03 17:46:15 +0100 (Sat, 03 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/fpdocxmlopts.pas
M /trunk/utils/fpdoc/mgrfpdocproj.pp
M /trunk/utils/fpdoc/mkfpdocproj.lpi
M /trunk/utils/fpdoc/mkfpdocproj.pp

* Some fixes after first test round
r19752 | michael | 2011-12-04 19:15:55 +0100 (Sun, 04 Dec 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Added logging options
r19753 | michael | 2011-12-04 19:16:51 +0100 (Sun, 04 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp
M /trunk/utils/fpdoc/dw_html.pp
M /trunk/utils/fpdoc/dwriter.pp
M /trunk/utils/fpdoc/fpdoc.lpi
M /trunk/utils/fpdoc/fpdoc.pp
A /trunk/utils/fpdoc/mkfpdoc.pp

Logging options implemented, and dry run. Separated out creation and logging logic
r19755 | michael | 2011-12-04 20:36:36 +0100 (Sun, 04 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp
M /trunk/utils/fpdoc/fpdoc.pp

* Implemented --descr-dir and --input-dir
r19761 | michael | 2011-12-05 20:30:22 +0100 (Mon, 05 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/fpdocxmlopts.pas
M /trunk/utils/fpdoc/mgrfpdocproj.pp
M /trunk/utils/fpdoc/mkfpdocproj.pp

* Save/load package imports to/from package description file
r19776 | michael | 2011-12-07 22:08:20 +0100 (Wed, 07 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/mkfpdocproj.pp

* Print usage message
r19786 | michael | 2011-12-09 11:54:07 +0100 (Fri, 09 Dec 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp

* Fixed external name case for procedure
r19795 | michael | 2011-12-10 14:32:17 +0100 (Sat, 10 Dec 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Fix bug #20791
r19796 | michael | 2011-12-10 15:03:13 +0100 (Sat, 10 Dec 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Speed Improvements and option to use (virtual file) streams.
r19797 | michael | 2011-12-10 15:16:54 +0100 (Sat, 10 Dec 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp

* Forgot to commit
r19798 | michael | 2011-12-10 15:20:55 +0100 (Sat, 10 Dec 2011) | 1 line
Changed paths:
A /trunk/packages/fcl-passrc/tests
A /trunk/packages/fcl-passrc/tests/tcscanner.pas
A /trunk/packages/fcl-passrc/tests/testpassrc.lpi
A /trunk/packages/fcl-passrc/tests/testpassrc.lpr

* Unit Tests for scanner
r19850 | michael | 2011-12-14 23:34:05 +0100 (Wed, 14 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/unitdiff.pp

* Corrected program name clause
r19884 | michael | 2011-12-23 16:05:18 +0100 (Fri, 23 Dec 2011) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dglobals.pp
M /trunk/utils/fpdoc/fpdoc.pp

* Extended usage with additional options for project file
r19901 | marco | 2011-12-28 20:08:40 +0100 (Wed, 28 Dec 2011) | 4 lines
Changed paths:
M /trunk/utils/fpdoc/Makefile
M /trunk/utils/fpdoc/Makefile.fpc
M /trunk/utils/fpdoc/dw_html.pp
M /trunk/utils/fpdoc/dwriter.pp

* improved unknown link errormsg to list current module name.
* Added some new units to clean rules. rst and main program objectcode
are still not cleaned properly though
r19903 | marco | 2011-12-29 00:00:56 +0100 (Thu, 29 Dec 2011) | 10 lines
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp

* fix for crash while building LCL docs. Hopefully the last one.
The fix is an emergency fix only, disabling calling convention
registration for element types that not derive from TPasProcedure

The fix is in Parsprocedureorfunctionheader, second part that handles
modifiers and calling conventions. The parent was always typecasted
to TPasProcedure, but can also be TPasProcedureType and TPasFunctionType
that not derive from TPasProcedure.
r19951 | joost | 2012-01-02 16:16:52 +0100 (Mon, 02 Jan 2012) | 3 lines
Changed paths:
M /trunk/packages/fastcgi/Makefile
M /trunk/packages/fcl-async/Makefile
M /trunk/packages/fcl-base/Makefile
M /trunk/packages/fcl-extra/Makefile
M /trunk/packages/fcl-image/Makefile
M /trunk/packages/fcl-js/Makefile
M /trunk/packages/fcl-json/Makefile
M /trunk/packages/fcl-net/Makefile
M /trunk/packages/fcl-passrc/Makefile
M /trunk/packages/fcl-registry/Makefile
M /trunk/packages/fcl-res/Makefile
M /trunk/packages/fcl-web/Makefile
M /trunk/utils/fpcm/fpcmake.inc
M /trunk/utils/fpcm/fpcmake.ini

* Do not use the BINUTILSPREFIX when compiling fpmake files during a cross-
compile. It seems that CROSSBOOTSTRAP is never set(?)
r19993 | michael | 2012-01-07 16:20:43 +0100 (Sat, 07 Jan 2012) | 4 lines
Changed paths:
M /trunk/packages/fcl-passrc/src/pastree.pp
M /trunk/packages/fcl-passrc/src/pparser.pp

* Allow streams as source
* Improved range type parsing (handle deprecated etc.)
* Improvements in record type parsing type (handle deprecated etc.)
r19996 | michael | 2012-01-07 19:41:08 +0100 (Sat, 07 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pscanner.pp
M /trunk/packages/fcl-passrc/tests/tcscanner.pas

* Macro support. Fix for include support if not EOL
r19997 | michael | 2012-01-07 21:36:22 +0100 (Sat, 07 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pscanner.pp
M /trunk/packages/fcl-passrc/tests/tcscanner.pas

* $IFDEF also handles macros
r20005 | marco | 2012-01-08 01:46:57 +0100 (Sun, 08 Jan 2012) | 2 lines
Changed paths:
M /trunk/utils/fpdoc/dw_dxml.pp

* emergency fix for breakage (TPasResString.value was still used. Changed to getdeclaration for now)
r20009 | michael | 2012-01-08 15:52:18 +0100 (Sun, 08 Jan 2012) | 1 line
Changed paths:
M /trunk/utils/fpdoc/dw_html.pp

* Fixed compilation with latest version of fcl-passrc
r20011 | michael | 2012-01-08 18:39:21 +0100 (Sun, 08 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pscanner.pp

* Handle* is now virtual.
r20012 | michael | 2012-01-08 18:42:50 +0100 (Sun, 08 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pastree.pp

* Added custom data object to TPasElement.
r20013 | michael | 2012-01-08 18:49:36 +0100 (Sun, 08 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/src/pparser.pp

* TokenIsCallingConvention and TokenIsProcedureModifier introduced for implementation of custom modifiers and calling conventions
r20014 | michael | 2012-01-08 19:17:10 +0100 (Sun, 08 Jan 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-passrc/tests/tcscanner.pas

* Test for special macro handling

git-svn-id: branches/fixes_2_6@22301 -

marco 13 роки тому
батько
коміт
3cded64f99

+ 7 - 0
.gitattributes

@@ -2228,6 +2228,9 @@ packages/fcl-passrc/src/paswrite.pp svneol=native#text/plain
 packages/fcl-passrc/src/pparser.pp svneol=native#text/plain
 packages/fcl-passrc/src/pscanner.pp svneol=native#text/plain
 packages/fcl-passrc/src/readme.txt svneol=native#text/plain
+packages/fcl-passrc/tests/tcscanner.pas svneol=native#text/plain
+packages/fcl-passrc/tests/testpassrc.lpi svneol=native#text/plain
+packages/fcl-passrc/tests/testpassrc.lpr svneol=native#text/plain
 packages/fcl-process/Makefile svneol=native#text/plain
 packages/fcl-process/Makefile.fpc svneol=native#text/plain
 packages/fcl-process/fpmake.pp svneol=native#text/plain
@@ -12903,6 +12906,10 @@ utils/fpdoc/intl/fpdocstr.de.po svneol=native#text/plain
 utils/fpdoc/intl/makeskel.de.po svneol=native#text/plain
 utils/fpdoc/makeskel.lpi svneol=native#text/plain
 utils/fpdoc/makeskel.pp svneol=native#text/plain
+utils/fpdoc/mgrfpdocproj.pp svneol=native#text/plain
+utils/fpdoc/mkfpdoc.pp svneol=native#text/plain
+utils/fpdoc/mkfpdocproj.lpi svneol=native#text/plain
+utils/fpdoc/mkfpdocproj.pp svneol=native#text/plain
 utils/fpdoc/sample-project.xml svneol=native#text/plain
 utils/fpdoc/sh_pas.pp svneol=native#text/plain
 utils/fpdoc/testunit.pp svneol=native#text/plain

+ 165 - 129
packages/fcl-passrc/examples/test_parser.pp

@@ -107,7 +107,7 @@
 
     TPasPackage = class(TPasElement)
       |
-    Modules: TList;
+    Modules: TFPList;
 
     TPasModule = class(TPasElement)
       |-InterfaceSection: TInterfaceSection;
@@ -115,27 +115,27 @@
       |
       |-ImplementationSection: TImplementationSection;
       |  |-Declarations -> full declaration, unit and program
-      |     |-Functions: TList;
+      |     |-Functions: TFPList;
       |        |-TPasFunction = class(TPasProcedureBase)
       |           |-Body: TProcedureBody;
       |              |-Declarations -> declaration and sub function
       |              |-Body: TPasImplBlock; -> procedure block
       |
       |-InitializationSection: TInitializationSection;
-      |  |-TPasImplBlock.Elements: TList; -> main block
+      |  |-TPasImplBlock.Elements: TFPList; -> main block
       |
       |-FinalizationSection: TFinalizationSection;
-         |-TPasImplBlock.Elements: TList; -> unit only
+         |-TPasImplBlock.Elements: TFPList; -> unit only
 
     Declarations = class(TPasElement)
-      |-Declarations: TList; -> the following are all in here
-      |-ResStrings: TList;
-      |-Types: TList;
-      |-Consts: TList;
-      |-Classes: TList;
-      |-Functions: TList;
-      |-Variables: TList;
-      |-Properties: TList;
+      |-Declarations: TFPList; -> the following are all in here
+      |-ResStrings: TFPList;
+      |-Types: TFPList;
+      |-Consts: TFPList;
+      |-Classes: TFPList;
+      |-Functions: TFPList;
+      |-Variables: TFPList;
+      |-Properties: TFPList;
     }
 
 
@@ -859,7 +859,7 @@ procedure GetTPasVar(lpv:TPasVariable; lindent:integer; NoLF:boolean);//BUG stri
   
 //write out a list of variables only
 //more compact than the output of seperate calls of GetTPasVar
-procedure GetPasVariables(vl:TList; lindent:integer; NoLF,NoSEM:boolean);
+procedure GetPasVariables(vl:TFPList; lindent:integer; NoLF,NoSEM:boolean);
    var v,i,j:integer;
        s,s1:string;
        prct:TPasRecordType;
@@ -1021,6 +1021,96 @@ procedure GetPasVariables(vl:TList; lindent:integer; NoLF,NoSEM:boolean);
     if not NoLF then writeln;
   end;  
   
+function GetTPasArgumentAccess(acc:TArgumentAccess):String;
+
+begin
+  Result:='';
+  case acc of
+    //argDefault:Result:='default'; //normal proccall is default
+    argConst:Result:='const';
+    argVar:Result:='var';
+    argOut:Result:='out';
+  end;
+end;
+
+procedure GetTPasProcedureType(lppt:TPasProcedureType; indent:integer);
+
+Var
+  l : integer;
+  lpa:TPasArgument;
+  samevar:array of integer;//same index same type
+  aktaa:TArgumentAccess;
+  svi:integer;
+  same:boolean;
+  aktname,tmpname:String;
+
+begin
+  if assigned(lppt.Args) and (lppt.Args.Count > 0) then
+    begin
+    write('(');
+    if lppt.Args.Count > 0 then
+     begin
+      //produce more compact output than the commented block below
+      //>find same declaration
+      //look ahead what is the same
+      SetLength(samevar,lppt.Args.Count);
+      svi:=0;
+      aktname:='';
+      for l:=0 to lppt.Args.Count-1 do
+       begin
+        same:=true;
+        tmpname:='';
+        lpa:=TPasArgument(lppt.Args.Items[l]);
+        if assigned(lpa.ArgType) then
+         begin
+          if lpa.ArgType is TPasArrayType then
+           begin
+             if assigned(TPasArrayType(lpa.ArgType).ElType) then tmpname:=TPasArrayType(lpa.ArgType).ElType.Name;
+           end
+            else tmpname:=TPasType(lpa.ArgType).Name;
+         end;
+        if l=0 then begin aktaa:=lpa.Access; aktname:=tmpname; end;
+        if lpa.Access <> aktaa then begin same:=false; aktaa:=lpa.Access; end;//access type
+        if (tmpname = '')or(tmpname <> aktname) then begin same:=false; aktname:=tmpname; end;//type name
+        if lpa.Value <> '' then same:=false;//var=value
+        if not same then inc(svi);
+        samevar[l]:=svi;
+       end;
+     //find same declaration<
+     svi:=-1;
+     same:=false;
+     for l:=0 to lppt.Args.Count-1 do
+      begin
+       lpa:=TPasArgument(lppt.Args.Items[l]);
+       if svi <> samevar[l] then
+        begin
+         svi:=samevar[l];
+         if lpa.Access <> argDefault then write(GetTPasArgumentAccess(lpa.Access),' ');
+         write(lpa.Name);//variblenname
+        end
+          else write(lpa.Name);
+       if (l < lppt.Args.Count-1)and(samevar[l+1]=svi) then write(',')
+        else
+         begin
+          if assigned(lpa.ArgType) then
+           begin
+            write(': ');
+            if lpa.ArgType is TPasArrayType then
+             GetTPasArrayType(TPasArrayType(lpa.ArgType))
+              else write(TPasType(lpa.ArgType).Name);
+           end;
+          if lpa.Value <> '' then write('=',lpa.Value);
+          if l< lppt.Args.Count-1 then write('; ');
+        end;
+      end;
+    write(')');
+    end;
+    end;
+  if (lppt is TPasFunctionType) then
+      write(': ',TPasFunctionType(lppt).ResultEl.ResultType.Name);
+  if lppt.IsOfObject then
+    write(' of Object');
+end;
 
 procedure GetTypes(pe:TPasElement; lindent:integer);
   var i,j,k:integer;
@@ -1110,7 +1200,12 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
    end
   else if pe is TPasProcedureType then
    begin
-    writeln('procedure');
+   if pe is TPasFunctionType then
+     Write('function ')
+   else
+     Write('procedure ');
+   GetTPasProcedureType(TPasProcedureType(pe), lindent);
+   Writeln(';');
    end
   else if pe is TPasPointerType then
    begin
@@ -1166,27 +1261,29 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
     writeln('set of ',pst.EnumType.Name,';');
    end
   else if pe is TPasClassOfType then writeln('Class of ',TPasClassOfType(pe).DestType.Name,';')
+  else if pe is tPasAliasType then
+    begin
+    pe:=tPasAliasType(PE).DestType;
+    write(PE.name);
+    if pe is tPasStringType then
+      begin
+      if (TPasStringType(PE).LengthExpr<>'') then
+        Write('[',TPasStringType(PE).LengthExpr,']');
+      end;
+    Writeln(';');
+    end
+  else if pe is tPasUnresolvedTypeRef then writeln(TPasUnresolvedTypeRef(PE).name,';')
   else
    begin
     
     writeln('{ Unknown TYPE(s): ');
-    writeln(s,pe.Name);
+    writeln(s,pe.Name,' ',pe.classname);
     writeln('}');
     writeln;
    end;
  end;
 
 
- function GetTPasArgumentAccess(acc:TArgumentAccess):String;
-  begin
-   Result:='';
-   case acc of
-     //argDefault:Result:='default'; //normal proccall is default
-     argConst:Result:='const';
-     argVar:Result:='var';
-     argOut:Result:='out';
-   end;
-  end;
 
  procedure GetTCallingConvention(cc:TCallingConvention);  //TODO: test it
   begin
@@ -1213,14 +1310,8 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
   procedure GetTPasProcedure(lpp:TPasProcedure; indent:integer);
    var l:integer;
        lppt:TPasProcedureType;
-       lpa:TPasArgument;
        s:String;
        
-       same:boolean;
-       samevar:array of integer;//same index same type
-       aktaa:TArgumentAccess;
-       aktname,tmpname:String;
-       svi:integer;
 
   begin
    if not Assigned(lpp) then exit;
@@ -1237,93 +1328,7 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
    if assigned(lpp.ProcType) then
     begin
      lppt:=lpp.ProcType;
-     if assigned(lppt.Args) and (lppt.Args.Count > 0) then
-      begin
-       write('(');
-       if lppt.Args.Count > 0 then 
-        begin
-         //produce more compact output than the commented block below
-         //>find same declaration
-         //look ahead what is the same
-         SetLength(samevar,lppt.Args.Count);
-         svi:=0;
-         aktname:='';
-         for l:=0 to lppt.Args.Count-1 do
-          begin
-           same:=true;
-           tmpname:='';
-           lpa:=TPasArgument(lppt.Args.Items[l]);
-           if assigned(lpa.ArgType) then
-            begin
-             if lpa.ArgType is TPasArrayType then
-              begin
-                if assigned(TPasArrayType(lpa.ArgType).ElType) then tmpname:=TPasArrayType(lpa.ArgType).ElType.Name;
-              end
-               else tmpname:=TPasType(lpa.ArgType).Name;
-            end;
-           if l=0 then begin aktaa:=lpa.Access; aktname:=tmpname; end;   
-           if lpa.Access <> aktaa then begin same:=false; aktaa:=lpa.Access; end;//access type 
-           if (tmpname = '')or(tmpname <> aktname) then begin same:=false; aktname:=tmpname; end;//type name
-           if lpa.Value <> '' then same:=false;//var=value
-           if not same then inc(svi); 
-           samevar[l]:=svi;
-          end; 
-        //find same declaration<  
-        svi:=-1;
-        same:=false;
-        for l:=0 to lppt.Args.Count-1 do
-         begin
-          lpa:=TPasArgument(lppt.Args.Items[l]);
-          if svi <> samevar[l] then
-           begin
-            svi:=samevar[l];
-            if lpa.Access <> argDefault then write(GetTPasArgumentAccess(lpa.Access),' '); 
-            write(lpa.Name);//variblenname
-           end
-             else write(lpa.Name); 
-          if (l < lppt.Args.Count-1)and(samevar[l+1]=svi) then write(',')
-           else
-            begin
-             if assigned(lpa.ArgType) then
-              begin
-               write(': ');
-               if lpa.ArgType is TPasArrayType then
-                GetTPasArrayType(TPasArrayType(lpa.ArgType))
-                 else write(TPasType(lpa.ArgType).Name);
-              end;
-             if lpa.Value <> '' then write('=',lpa.Value);
-             if l< lppt.Args.Count-1 then write('; ');
-           end;    
-         end; 
-       {//simple version duplicates declarations of same type
-        for l:=0 to lppt.Args.Count-1 do
-        begin
-         lpa:=TPasArgument(lppt.Args.Items[l]);
-          if lpa.Access <> argDefault then write(GetTPasArgumentAccess(lpa.Access),' '); 
-         write(lpa.Name);//variblenname
-         if assigned(lpa.ArgType) then
-          begin
-           //if TPasType(lpa.ArgType).ElementTypeName <>'unresolved type reference' then
-           //,TPasType(lpa.ArgType).Name,' ');
-           //,TPasType(lpa.ArgType).FullName,TPasType(lpa.ArgType).ElementTypeName)
-           // PParser 2099: ArgType := nil; if IsUntyped then => Arg.ArgType := ArgType;
-           //     else write(':? ');
-           write(': ');
-           if lpa.ArgType is TPasArrayType then
-            begin
-             GetTPasArrayType(TPasArrayType(lpa.ArgType));
-            end
-             else  write(TPasType(lpa.ArgType).Name);
-          end;
-         if lpa.Value <> '' then write('=',lpa.Value);
-         if l< lppt.Args.Count-1 then write('; ');
-        end;}
-        end;
-       write(')');
-      end;
-     if lppt.IsOfObject then write(' of Object'); 
-     if (TPasElement(lpp) is TPasFunction)or(TPasElement(lpp) is TPasClassFunction) then 
-         write(': ',TPasFunctionType(lpp.ProcType).ResultEl.ResultType.Name);
+     GetTPasProcedureType(lppt,Indent);
     end;
    //writeln(';');
    WriteFmt(false,'',true);
@@ -1425,7 +1430,7 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
        lpp:TPasProperty;
        lpa:TPasArgument;
        vis:TPasMemberVisibility;
-       vars:TList;
+       vars:TFPList;
        IsVar:boolean;
 
   procedure PrintVars;
@@ -1439,32 +1444,63 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
    if assigned(pc) then
     begin
      s:=GetIndent(indent);
-     write(s,pc.Name,'=');
+     if (pc.ObjKind=okGeneric) then
+       begin
+       write(s,'generic ',pc.Name);
+       for l:=0 to pc.GenericTemplateTypes.Count-1 do
+          begin
+          if l=0 then
+           Write('<')
+          else
+           Write(',');
+          Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
+          end;
+       Write('> = ');
+       end
+     else
+       write(s,pc.Name,' = ');
      if pc.IsPacked then write('packed ');
      case pc.ObjKind of
       okObject:write('Object');
       okClass:write('Class');
       okInterface:write('Interface');
+      okGeneric:write('class');
+      okspecialize : write('specialize');
      end;
      if assigned(pc.AncestorType) and (pc.AncestorType.ElementTypeName <> '') then
-        write('(',pc.AncestorType.Name,')');
-
+        begin
+        if pc.ObjKind<>okspecialize then
+          write('(',pc.AncestorType.Name,')')
+        else
+          begin
+          write(' ',pc.AncestorType.Name);
+          for l:=0 to pc.GenericTemplateTypes.Count-1 do
+           begin
+           if l=0 then
+            Write('<')
+           else
+            Write(',');
+           Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
+           end;
+          Write('>');
+          end;
+        end;
      if pc.IsForward or pc.IsShortDefinition then //pparser.pp: 3417 :class(anchestor); is allowed !
       begin
        writeln(';');
        exit;
       end;  
-    //Members: TList;
+    //Members: TFPList;
     //InterfaceGUID: String;
-    //ClassVars: TList; //is this always empty ?
+    //ClassVars: TFPList; //is this always empty ?
     //Modifiers: TStringList;
-    //Interfaces: TList;
+    //Interfaces: TFPList;
       s1:=GetIndent(indent+1);
       s2:=GetIndent(indent+2);
       if pc.Members.Count > 0 then
        begin
         writeln;
-        vars:=TList.Create;
+        vars:=TFPList.Create;
         IsVar:=false;
         for j:=0 to pc.Members.Count-1 do
          begin
@@ -1562,6 +1598,7 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
          vars.free;
        end
         else  writeln;//(';'); //x=class(y);
+
      writeln(s,'end;');
     end;
   end;
@@ -1574,7 +1611,7 @@ procedure GetDecls(Decl:TPasDeclarations; indent:integer);
      ps:TPasSection;
      s:string;
      x:(None,ResStrings,Types,Consts,Classes,Functions,Variables,Properties);
-     l:TList;
+     l:TFPList;
 
   procedure PrintVars;
    begin
@@ -1586,7 +1623,7 @@ begin
  x:=None;
  if assigned(Decl)then
   begin
-   l:=TList.Create;
+   l:=TFPList.Create;
    pe:=TPasElement(Decl);
    if pe is TPasSection then
     begin
@@ -1882,7 +1919,6 @@ begin
           raise;
        end;
     end;
-
    if M is TPasProgram then
     begin
      writeln('Program ',M.Name,';');

+ 332 - 81
packages/fcl-passrc/examples/testunit1.pp

@@ -12,6 +12,10 @@ interface
  uses 
   SysUtils,Classes;
 
+
+resourcestring
+ SParserErrorAtToken = 'parser error at token';
+ 
  const
   AnIntegerConst=1;
   AStringConst='Hello, World!';
@@ -24,11 +28,31 @@ interface
   ADeprecatedConst=1 deprecated;
    
  Type
+  TLineEndStr = string [3];
+
+  TDeprecatedType = Integer deprecated;
+  TDeprecatedRecord = Record
+    x,Y : Integer; 
+  end deprecated;
+  TDeprecatedFieldsRecord = Record
+    x,Y : Integer deprecated; 
+  end;
+  TDeprecatedFieldsRecord2 = Record
+    x,Y : Integer deprecated
+  end;
   TAnEnumType=(one,two,three);
   TASetType=set of TAnEnumType;
+  TIntegerSet = Set of 0..SizeOf(Integer)*8-1;
   TAnArrayType=Array[1..10] of Integer;
   TASubRangeType=one..two;
   TABooleanArrayType=Array[Boolean] of Integer;  
+  TDay = (monday,tuesday,wednesday,thursday,friday,saturday,sunday);
+  TShortDay = (mon,tue,wed,thu,fri,sat,sun);
+  TShortDays = set of TShortDay;
+  TDays = set of TDay;
+  TMyInteger = Integer;
+  ADouble = type double;
+  arangetypealias = type 0..$FF;
   TARecordType=record
                    X,Y: Integer;
                    Z: String;
@@ -54,9 +78,36 @@ interface
                  3 : (Z : Longint);  
                  );  
           end;                           
+
+TYPE
+   PPoint = ^TPoint;
+   TPoint = OBJECT
+      X, Y: Sw_Integer;
+   END;
+
+   PRect = ^TRect;
+   TRect = OBJECT
+      A, B: TPoint;                                { Corner points }
+      FUNCTION Empty: Boolean;
+      FUNCTION Equals (R: TRect): Boolean;
+      FUNCTION Contains (P: TPoint): Boolean;
+      PROCEDURE Copy (R: TRect);
+      PROCEDURE Union (R: TRect);
+      PROCEDURE Intersect (R: TRect);
+      PROCEDURE Move (ADX, ADY: Sw_Integer);
+      PROCEDURE Grow (ADX, ADY: Sw_Integer);
+      PROCEDURE Assign (XA, YA, XB, YB: Sw_Integer);
+   END;
+               
+
+  TNotifyEvent = Procedure (Sender : TObject) of object;
+  TNotifyEvent2 = Function (Sender : TObject) : Integer of object;
+ 
                           
 //  TADeprecatedType = Integer deprecated;
-
+  TMyChildClass = Class;
+  MyInterface = Interface;
+  
   { TMyParentClass }
 
   TMyParentClass=Class(TComponent)
@@ -99,18 +150,47 @@ interface
   Published
     Property AProtectedProp;
   end;
-  
- TPasFunctionType=Class(TPasProcedureType)
+  TC = TMyChildClass;
+
+  TPasFunctionType=Class(TObject)
   public
     destructor Destroy; override;
-    Class Function TypeName: string; override;
-    Function ElementTypeName: string; override;
-    Function GetDeclaration(Full: boolean): string; override;
+    Class Function TypeName: string;
+    Function ElementTypeName: string; 
+    Function GetDeclaration(Full: boolean): string; 
+    Procedure Something;  strict
+  Private  
+    Procedure SomethingElse;
   public
-    ResultEl: TPasResultElement;
+    ResultEl: TObject;
   end; 
-                        
- var
+
+  TPropModifiers = Class(TObject)
+  Private
+    FB : Integer;
+    Function IsStored : Boolean;
+    Function GetI(AI : Integer) : Integer;
+    Procedure SetI(AI : Integer; AVal : Integer);
+  Published
+    Property A : Integer Read FB Write FB Stored False;
+    Property B : Integer Read FB Write FB Stored True;
+    Property C : Integer Read FB Write FB Stored IsStored;
+    Property D : Integer Read FB Write FB Default 1;
+    Property E : Integer Read FB Write FB Stored True Default 1;
+  Public
+    Property Ints[AI : Integer] : Integer Read GetI Write SetI; default;
+  end;
+  
+  TPropModifiers2 = class(TPropModifiers)
+  Public
+    Property Ints[AI : Integer] : Integer Read GetI Write SetI; default; deprecated;
+  end;                          
+  
+  TEdit = Class(TObject)
+    Text : String;
+  end;
+  
+var
   ASimpleVar: Integer;  
   ATypedVar: TMethod;
   ARecordVar: Record
@@ -122,8 +202,16 @@ interface
   
   ADeprecatedVar: Integer deprecated;
   ACVarVar: Integer ; cvar;
-  AnExternalVar: Integer ;external name 'avar';
-  AnExternalLibVar: Integer ;external 'library' name 'avar';
+  AnExternalVar1: Integer; external;
+  AnExternalVar2: Integer; external name 'avar';
+  AnExternalLibVar: Integer; external 'library' name 'avar';
+  APublicVar : String; public;
+  APublicVar2 : String; public name 'ANAME';
+  APublicVar3 : String; export;
+  APublicVar4 : String; export name 'nono';
+  APublicVar5 : String; cvar; external;
+  APublicVar6 : String; external name 'me';
+  APublicVar7 : String deprecated; external name 'me';
       
  Procedure SimpleProc;
  Procedure OverloadedProc(A: Integer);
@@ -146,17 +234,31 @@ interface
  Procedure externalproc; external;
  Procedure externalnameProc; external name 'aname';
  Procedure externallibnameProc; external 'alibrary' name 'aname';
+ Function  hi(q : QWord) : DWord;   [INTERNPROC: fpc_in_hi_qword];
 
-  
+ 
+Type
+ generic TFPGListEnumerator<T> = class(TObject)
+ protected
+    FList: TFPList;
+    FPosition: Integer;
+    function GetCurrent: T;
+ end;                 
+ TFPGListEnumeratorSpec = specialize TFPGListEnumerator<TPasFunctionType>; 
+
+ 
 Implementation
 
 
  Procedure SimpleProc;
 
- procedure  SubProc;
+  procedure  SubProc;
+  Var S : String;
   begin
    s:= s+'a';
   end;
+ Var
+   a,B,c,i : integer;
 
  begin
   a:= 1;
@@ -166,6 +268,8 @@ Implementation
  end;
 
  Procedure OverloadedProc(A: Integer);
+ Var
+   i : integer;
  begin
   if i=1 then ;
  end;
@@ -229,7 +333,11 @@ Implementation
  end;
 
  procedure TMyChildClass.AnAbstractProc;
+ 
  procedure  SubCProc;
+ 
+   Var sc : string;
+   
   begin
    sc:= sc+'ac';
   end;
@@ -300,12 +408,142 @@ Implementation
  procedure TMyParentClass.SomePublishedMethod;
  begin
  end;
- 
+
+
  Class Function TPasFunctionType.TypeName: String;
  begin
   Result:= 'Function';
  end;
 
+Type
+  TI = Class(TComponent)
+  Public
+    FP : Integer;
+    Procedure SetP1(A : Integer); virtual;
+    Procedure M1;virtual;
+    Function F1  : Integer; virtual;
+    procedure test; virtual;
+    property P : Integer Read FP Write SetP1;
+  end;
+  
+  Procedure TI.M1;
+  begin
+  end;
+  Procedure TI.Test;
+  begin
+  end;
+  Function TI.F1 : Integer; 
+  begin
+  Result:=0;
+  end;
+  Procedure TI.SetP1(A : Integer);
+  begin
+    FP:=A;
+  end;
+  
+TYpe
+  TI2 = Class(TI)
+  procedure write(s : string);
+  Procedure SetP1(A : Integer); override;
+  Procedure M1;override;
+  Procedure Test;override;
+  Function F1 : integer; override;
+  procedure donothing;
+  property P : Integer Read F1 Write SetP1;
+  end;
+  Procedure TI2.M1;
+  begin
+    Inherited;
+  end;
+  Procedure TI2.Write(s : string);
+  begin
+    writeln(s);
+  end;
+  Function TI2.F1 :Integer; 
+  begin
+     Result:=0;
+  end;
+  Procedure TI2.Test;
+  begin
+  if true then
+    Inherited Test
+  else
+    DoNothing;
+    Inherited test;
+   if true then
+     Inherited
+   else
+     DoNothing;
+  end;
+  Procedure TI2.DoNothing;
+    function escapetext(s : string) : string;
+    begin
+    end;
+  var
+  Atext : string;
+  begin
+    Self.Write(EscapeText(AText)); 
+    TComponent.Create(Self);
+  end;
+  Procedure TI2.SetP1(A : Integer);
+  begin
+    FP:=A;
+    Inherited P:= 3;
+    Inherited SetP1(3);
+    Inherited P:= Ord(A);
+  end;
+
+
+ procedure usage;
+ begin
+ end;
+ Procedure DoSomething;
+ begin
+ end;
+ Procedure DoSomethingElse;
+ begin
+ end;
+ procedure stat1;
+ begin
+ end;
+ procedure stat2;
+ begin
+ end;
+ procedure stat3;
+ begin
+ end;
+ procedure stat4;
+ begin
+ end;
+ procedure stat5;
+ begin
+ end;
+ procedure stat6;
+ begin
+ end;
+ procedure stat7;
+ begin
+ end;
+  procedure stat8;
+ begin
+ end;
+ procedure stat9;
+ begin
+ end;
+ procedure doit;
+ begin
+ end;
+ procedure statement;
+ begin
+ end;
+ procedure work;
+ begin
+ end;
+ procedure kissdwarf(i : integer);
+ 
+ begin
+   writeln('kiss dwarf',i);
+ end;
  procedure Statements;
  const
   cint=1;
@@ -340,14 +578,32 @@ Implementation
   AR=record
       X,Y: LongInt;
      end;
+  TScanner = record
+   currow,curcolumn : integer;
+   curfilename : string;
+  end;  
+
   //PAR = Record;
  var
+  msg,curtokenname : string;
   TheCustomer: Passenger;
   L: ^LongInt;
   P: PPChar;
   S,T: Ar;
-      
+  M, X,Y : Double;
+  Done : Boolean;
+  Weather,Good: Boolean;  
+  c : char;
+  j,dwarfs,i,Number,Block : integer;
+  exp1,exp2,exp3,exp4,exp5,exp6,exp7,exp8,exp9 : boolean;
+  o : Tobject;
+  day,today : tday;
+  A,B,D : Passenger;
+  E : Exception;
+  scanner : tscanner;
+    
  begin
+  O:=Nil;
   X:= X+Y;
   //EparserError on C++ style
   //X+=Y;      { Same as X := X+Y, needs -Sc command line switch}
@@ -368,7 +624,7 @@ Implementation
   //Goto jumpto;
 
   Case i of
-    3: DoSomething;
+    6: DoSomething;
     1..5: DoSomethingElse;
   end;
 
@@ -426,19 +682,19 @@ Implementation
   else
     stat2;
 
- if i is integer then
+ if o is TObject then
   begin
-    write('integer');
+    write('object');
   end
   else 
-    if i is real then 
+    if o is TMyParentClass then 
   begin
     write('real');
   end
   else 
     write('0'); 
 
-  if Today in[Monday..Friday] then
+  if Today in [Monday..Friday] then
     WriteLn('Must work harder')
   else
     WriteLn('Take a day off.');
@@ -472,21 +728,21 @@ Implementation
      I:= I+2;
     end;
     X:= X/2;
-    while x>=10e-3 do 
-      dec(x);
+    while i>=10e-3 do 
+      dec(i);
 
-    while x>0 do 
-    while y>0 do 
+    while i>0 do 
+    while j>0 do 
       begin
-	dec(x);
-	dec(y);
+	dec(i);
+	dec(j);
       end;
 
-    while x>0 do
-    if x>2 then 
-     dec(x)
+    while i>0 do
+    if i>2 then 
+     dec(i)
     else 
-     dec(x,2);
+     dec(i,2);
 
       X:= 2+3;
 
@@ -499,12 +755,11 @@ Implementation
        Flight:= 'PS901';
       end;
 
-  With A,B,C,D do
+  With A,B,D do
    Statement;
 
     With A do
      With B do
-      With C do
        With D do 
         Statement;
 
@@ -521,60 +776,77 @@ Implementation
 
     try
 	try
-	  M:= ParseSource(E,cmdl,'linux','i386');
+	  M:= Y;
 	except
 	  on excep: EParserError do
 	    begin
-	      writeln(excep.message,' line:',excep.row,' column:',excep.column,' file:',excep.filename);
+	      writeln(excep.message,' : ',excep.classname);
 	      raise ;
 	  end;
 	end;
-	Decls:= M.InterfaceSection.Declarations;
-	for I:= 0 to Decls.Count-1 do
-	  Writeln('Interface item ',I,': ');
-
 	FreeAndNil(M);
     finally
 	FreeAndNil(E)
    end;
    
-   raise EParserError.Create(Format(SParserErrorAtToken, [Msg, CurTokenName]) {$ifdef addlocation}+' ('+inttostr(scanner.currow)+' '+inttostr(scanner.curcolumn)+')'{$endif},Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn);
+   raise EParserError.Create(Format(SParserErrorAtToken, [Msg, CurTokenName]) {$ifdef addlocation}+' ('+inttostr(scanner.currow)+' '+inttostr(scanner.curcolumn)+')'{$endif});
     
     // try else
  end;
 
+ function addone : integer;
+ begin
+ end;
+  procedure myproc;
+  begin
+  end;
  procedure Expression;
+
+  Var
+    A,b,c,d,e,f,i,j : Integer;
+    x : double;
+    u : Boolean;
+    fu : function : integer;
+    ad : boolean;
+    z : tdays;
+    today,tomorrow : tday;
+    bs : set of byte;
+    cs : set of char;
+    cc : char;  
+    W : TShortDays;
+    buffer : array[1..10] of byte;
+    P : Pointer;
+    SErrMultipleSourceFiles,FileName,Dirname,S : string;
+    o,co : tobject;
+    
  begin
-  A:= a+b *c /(-e+f)*3 div 2 + 4 mod 5 - 2 shl 3 + 3 shr 1 ;
+  x:= a+b *c /(-e+f)*(3 div 2) + 4 mod 5 - 2 shl 3 + 3 shr 1 ;
   b:= (a and not b) or c xor d;
-  u:= i<=2 or a<>b or j>=3;
-  u:= i=1 or a>b or b<a or i<>2;
+  u:= (i<=2) or (a<>b) or (j>=3);
+  u:= (i=1) or (a>b) or (b<a) or (i<>2);
   u:= i in [1..2];
 
- If F=@AddOne Then  
+ If Fu=@AddOne Then  
   WriteLn('Functions are equal');
 
- If F()=Addone then  
+ If Fu()=Addone then  
   WriteLn('Functions return same values ');
 
  z:= [today,tomorrow];
  z:= [Monday..Friday,Sunday];
- z:= [2,3*2,6*2,9*2];
- z:= ['A'..'Z','a'..'z','0'..'9'];
+ bs:= [2,3*2,6*2,9*2];
+ cs:= ['A'..'Z','a'..'z','0'..'9'];
 
- x:= Byte('A');
- x:= Char(48);
- x:= boolean(1);
- x:= longint(@Buffer);
- x:= Integer('A');
- x:= Char(4875);
- x:= Word(@Buffer);
+ i:= Byte('A');
+ cc:= Char(48);
+ ad:= boolean(1);
+ i:= longint(@Buffer);
+ i:= Integer('A');
+ cc:= Char(225);
+ i:= Word(@Buffer);
 
  B:= Byte(C);
- Char(B):= C;
 
- TWordRec(W).L:= $FF;
- TWordRec(W).H:= 0;
  S:= TObject(P).ClassName;
 
  P:= @MyProc; //warum @ ? fix pparser 769 ?
@@ -585,31 +857,12 @@ Implementation
  W:= [mon,tue,wed]-[wed];     // equals [mon,tue]
  W:= [mon,tue,wed]*[wed,thu,fri]; // equals [wed] warum * ?
 
- (C as TEdit).Text:= 'Some text';
- C:= O as TComponent;
-
- if A is TComponent then ;
- If A is B then ;
-
- Inherited ;
- Inherited Test;
-
-  if true then
-    Inherited
-  else
-    DoNothing;
+ (Co as TEdit).Text:= 'Some text';
+ Co:= O as TComponent;
 
-  if true then
-    Inherited Test
-  else
-    DoNothing;
+ if co is TComponent then ;
+ If co is TC then ;
 
-   Inherited P:= 3;  
-   Inherited SetP1(3); 
-   Result:= Char(P and $FF);  
-   Result:= Char((Inherited P) and $FF);  
-   Inherited P:= Ord(AValue);
-   Result:= Inherited InterPretOption(Cmd,Arg);
 
   raise Exception.Create(SErrMultipleSourceFiles);
 
@@ -621,8 +874,6 @@ Implementation
 	else
 	  Filename:= s;
 
-  Self.Write(EscapeText(AText)); 
-  TObject.Create(Self);
  end;
 
  constructor TPasPackage.Create(const AName: String; AParent: TPasElement);

+ 207 - 64
packages/fcl-passrc/src/pastree.pp

@@ -42,9 +42,12 @@ resourcestring
   SPasTreeEnumType = 'enumeration type';
   SPasTreeSetType = 'set type';
   SPasTreeRecordType = 'record type';
+  SPasStringType = 'string type';
   SPasTreeObjectType = 'object';
   SPasTreeClassType = 'class';
   SPasTreeInterfaceType = 'interface';
+  SPasTreeGenericType = 'generic class';
+  SPasTreeSpecializedType = 'specialized class type';
   SPasTreeArgument = 'argument';
   SPasTreeProcedureType = 'procedure type';
   SPasTreeResultElement = 'function result';
@@ -83,6 +86,7 @@ type
     visStrictPrivate, visStrictProtected);
 
   TCallingConvention = (ccDefault,ccRegister,ccPascal,ccCDecl,ccStdCall,ccOldFPCCall,ccSafeCall);
+  TPackMode = (pmNone,pmPacked,pmBitPacked);
 
   TPasMemberVisibilities = set of TPasMemberVisibility;
   TPasMemberHint = (hDeprecated,hLibrary,hPlatform,hExperimental,hUnimplemented);
@@ -94,6 +98,7 @@ type
 
   TPasElement = class(TPasElementBase)
   private
+    FData: TObject;
     FRefCount: LongWord;
     FName: string;
     FParent: TPasElement;
@@ -112,12 +117,14 @@ type
     function PathName: string;          // = Module.Name + FullName
     function GetModule: TPasModule;
     function ElementTypeName: string; virtual;
+    Function HintsString : String;
     function GetDeclaration(full : Boolean) : string; virtual;
     procedure Accept(Visitor: TPassTreeVisitor); override;
     property RefCount: LongWord read FRefCount;
     property Name: string read FName write FName;
     property Parent: TPasElement read FParent;
     Property Hints : TPasMemberHints Read FHints Write FHints;
+    Property CustomData : TObject Read FData Write FData;
   end;
 
   TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst, pekRange,
@@ -238,7 +245,7 @@ type
     function ElementTypeName: string; override;
   public
     Declarations, ResStrings, Types, Consts, Classes,
-    Functions, Variables, Properties: TList;
+    Functions, Variables, Properties: TFPList;
   end;
 
   { TPasSection }
@@ -249,7 +256,7 @@ type
     destructor Destroy; override;
     procedure AddUnitToUsesList(const AUnitName: string);
   public
-    UsesList: TList;            // TPasUnresolvedTypeRef or TPasModule elements
+    UsesList: TFPList;            // TPasUnresolvedTypeRef or TPasModule elements
   end;
 
   { TInterfaceSection }
@@ -296,17 +303,18 @@ type
     destructor Destroy; override;
     function ElementTypeName: string; override;
   public
-    Modules: TList;     // List of TPasModule objects
+    Modules: TFPList;     // List of TPasModule objects
   end;
 
   { TPasResString }
 
   TPasResString = class(TPasElement)
   public
+    Destructor Destroy; override;
     function ElementTypeName: string; override;
     function GetDeclaration(full : Boolean) : string; Override;
   public
-    Value: string;
+    Expr: TPasExpr;
   end;
 
   { TPasType }
@@ -361,7 +369,10 @@ type
     function ElementTypeName: string; override;
     function GetDeclaration(full : boolean) : string; override;
   public
-    RangeStart, RangeEnd: string;
+    RangeExpr : TBinaryExpr;
+    Destructor Destroy; override;
+    Function RangeStart : String;
+    Function RangeEnd : String;
   end;
 
   { TPasArrayType }
@@ -373,8 +384,9 @@ type
     function GetDeclaration(full : boolean) : string; override;
   public
     IndexRange : string;
-    IsPacked : Boolean;          // 12/04/04 - Dave - Added
+    PackMode : TPackMode;
     ElType: TPasType;
+    Function IsPacked : Boolean;
   end;
 
   { TPasFileType }
@@ -394,8 +406,8 @@ type
   public
     function ElementTypeName: string; override;
   public
-    IsValueUsed: Boolean;
-    Value: Integer;
+//    IsValueUsed: Boolean;
+//    Value: Integer;
     AssignedValue : string;
   end;
 
@@ -409,7 +421,7 @@ type
     function GetDeclaration(full : boolean) : string; override;
     Procedure GetEnumNames(Names : TStrings);
   public
-    Values: TList;      // List of TPasEnumValue objects
+    Values: TFPList;      // List of TPasEnumValue objects
   end;
 
   { TPasSetType }
@@ -445,16 +457,17 @@ type
     function ElementTypeName: string; override;
     function GetDeclaration(full : boolean) : string; override;
   public
-    IsPacked: Boolean;
-    IsBitPacked : Boolean;
-    Members: TList;     // array of TPasVariable elements
+    PackMode : TPackMode;
+    Members: TFPList;     // array of TPasVariable elements
     VariantName: string;
     VariantType: TPasType;
-    Variants: TList;	// array of TPasVariant elements, may be nil!
+    Variants: TFPList;	// array of TPasVariant elements, may be nil!
+    Function IsPacked: Boolean;
+    Function IsBitPacked : Boolean;
   end;
 
-
-  TPasObjKind = (okObject, okClass, okInterface);
+  TPasGenericTemplateType = Class(TPasElement);
+  TPasObjKind = (okObject, okClass, okInterface, okGeneric, okSpecialize);
 
   { TPasClassType }
 
@@ -464,19 +477,23 @@ type
     destructor Destroy; override;
     function ElementTypeName: string; override;
   public
+    PackMode : TPackMode;
     ObjKind: TPasObjKind;
     AncestorType: TPasType;     // TPasClassType or TPasUnresolvedTypeRef
-    IsPacked: Boolean;        // 12/04/04 - Dave - Added
     IsForward : Boolean;
     IsShortDefinition: Boolean;//class(anchestor); without end
-    Members: TList;     // array of TPasElement objects
+    Members: TFPList;     // array of TPasElement objects
     InterfaceGUID : string; // 15/06/07 - Inoussa
 
-    ClassVars: TList;   // class vars
+    ClassVars: TFPList;   // class vars
     Modifiers: TStringList;
-    Interfaces : TList;
+    Interfaces : TFPList;
+    GenericTemplateTypes : TFPList;
+    Function IsPacked : Boolean;
   end;
 
+
+
   TArgumentAccess = (argDefault, argConst, argVar, argOut);
 
   { TPasArgument }
@@ -505,7 +522,8 @@ type
     function CreateArgument(const AName, AUnresolvedTypeName: string):TPasArgument;
   public
     IsOfObject: Boolean;
-    Args: TList;        // List of TPasArgument objects
+    Args: TFPList;        // List of TPasArgument objects
+    CallingConvention : TCallingConvention;
   end;
 
   { TPasResultElement }
@@ -537,12 +555,19 @@ type
     function ElementTypeName: string; override;
   end;
 
+  { TPasStringType }
+
+  TPasStringType = class(TPasUnresolvedTypeRef)
+  public
+    LengthExpr : String;
+    function ElementTypeName: string; override;
+  end;
+
   { TPasTypeRef }
 
   TPasTypeRef = class(TPasUnresolvedTypeRef)
   public
   public
-    // function GetDeclaration(full : Boolean): string; override;
     RefType: TPasType;
   end;
 
@@ -578,7 +603,7 @@ type
     function ElementTypeName: string; override;
     function GetDeclaration(full : boolean) : string; override;
   public
-    Args: TList;        // List of TPasArgument objects
+    Args: TFPList;        // List of TPasArgument objects
     IndexValue, ReadAccessorName, WriteAccessorName,ImplementsName,
       StoredAccessorName, DefaultValue: string;
     IsDefault, IsNodefault: Boolean;
@@ -600,13 +625,13 @@ type
     function ElementTypeName: string; override;
     function TypeName: string; override;
   public
-    Overloads: TList;           // List of TPasProcedure nodes
+    Overloads: TFPList;           // List of TPasProcedure nodes
   end;
 
   TProcedureModifier = (pmVirtual, pmDynamic, pmAbstract, pmOverride,
                         pmExported, pmOverload, pmMessage, pmReintroduce,
                         pmStatic,pmInline,pmAssembler,pmVarargs,
-                        pmCompilerProc,pmExternal,pmExtdecl,pmForward);
+                        pmCompilerProc,pmExternal,pmForward);
   TProcedureModifiers = Set of TProcedureModifier;
   TProcedureMessageType = (pmtInteger,pmtString);
                         
@@ -614,10 +639,11 @@ type
 
   TPasProcedure = class(TPasProcedureBase)
   Private
-    FCallingConvention : TCallingConvention;
     FModifiers : TProcedureModifiers;
     FMessageName : String;
     FMessageType : TProcedureMessageType;
+    function GetCallingConvention: TCallingConvention;
+    procedure SetCallingConvention(AValue: TCallingConvention);
   public
     destructor Destroy; override;
     function ElementTypeName: string; override;
@@ -640,7 +666,7 @@ type
     Function IsStatic : Boolean;
     Function IsForward: Boolean;
     Property Modifiers : TProcedureModifiers Read FModifiers Write FModifiers;
-    Property CallingConvention : TCallingConvention Read FCallingConvention Write FCallingConvention;
+    Property CallingConvention : TCallingConvention Read GetCallingConvention Write SetCallingConvention;
     Property MessageName : String Read FMessageName Write FMessageName;
     property MessageType : TProcedureMessageType Read FMessageType Write FMessageType;
   end;
@@ -702,7 +728,7 @@ type
     constructor Create(const AName: string; AParent: TPasElement); override;
     destructor Destroy; override;
   public
-    Labels: TList;
+    Labels: TFPList;
     Body: TPasImplBlock;
   end;
 
@@ -716,7 +742,7 @@ type
     function TypeName: string; virtual;
   public
     ProcType: TPasProcedureType;
-    Locals: TList;
+    Locals: TFPList;
     Body: TPasImplBlock;
   end;
 
@@ -808,7 +834,7 @@ type
     function AddSimple(exp: TPasExpr): TPasImplSimple;
     function CloseOnSemicolon: boolean; virtual;
   public
-    Elements: TList;    // TPasImplElement objects
+    Elements: TFPList;    // TPasImplElement objects
   end;
 
   { TPasImplStatement }
@@ -1012,7 +1038,7 @@ const
     'default', 'private', 'protected', 'public', 'published', 'automated','strict private', 'strict protected');
 
   ObjKindNames: array[TPasObjKind] of string = (
-    'object', 'class', 'interface');
+    'object', 'class', 'interface','class','class');
   
   OpcodeStrings : Array[TExprOpCode] of string = 
        ('','+','-','*','/','div','mod','**',
@@ -1026,11 +1052,16 @@ const
 
   cPasMemberHint : array[TPasMemberHint] of string =
       ( 'deprecated', 'library', 'platform', 'experimental', 'unimplemented' );
+  cCallingConventions : array[TCallingConvention] of string =
+      ( '', 'Register','Pascal','CDecl','StdCall','OldFPCCall','SafeCall');
 
 implementation
 
 uses SysUtils;
 
+{ TPasStringType }
+
+
 {$IFNDEF FPC}
   const
     LineEnding = sLineBreak;
@@ -1039,6 +1070,23 @@ uses SysUtils;
 { Parse tree element type name functions }
 
 function TPasElement.ElementTypeName: string; begin Result := SPasTreeElement end;
+
+function TPasElement.HintsString: String;
+
+Var
+  H : TPasmemberHint;
+
+begin
+  Result:='';
+  For H := Low(TPasmemberHint) to High(TPasMemberHint) do
+    if H in Hints then
+      begin
+      If (Result<>'') then
+        Result:=Result+'; ';
+      Result:=Result+cPasMemberHint[h];
+      end;
+end;
+
 function TPasDeclarations.ElementTypeName: string; begin Result := SPasTreeSection end;
 function TPasModule.ElementTypeName: string; begin Result := SPasTreeModule end;
 function TPasPackage.ElementTypeName: string; begin Result := SPasTreePackage end;
@@ -1074,6 +1122,7 @@ function TPasDestructor.ElementTypeName: string; begin Result := SPasTreeDestruc
 function TPasProcedureImpl.ElementTypeName: string; begin Result := SPasTreeProcedureImpl end;
 function TPasConstructorImpl.ElementTypeName: string; begin Result := SPasTreeConstructorImpl end;
 function TPasDestructorImpl.ElementTypeName: string; begin Result := SPasTreeDestructorImpl end;
+function TPasStringType.ElementTypeName: string; begin Result:=SPasStringType;end;
 
 function TPasClassType.ElementTypeName: string;
 begin
@@ -1081,9 +1130,16 @@ begin
     okObject: Result := SPasTreeObjectType;
     okClass: Result := SPasTreeClassType;
     okInterface: Result := SPasTreeInterfaceType;
+    okGeneric : Result := SPasTreeGenericType;
+    okSpecialize : Result := SPasTreeSpecializedType;
   end;
 end;
 
+function TPasClassType.IsPacked: Boolean;
+begin
+  Result:=PackMode<>pmNone;
+end;
+
 
 
 { All other stuff: }
@@ -1091,17 +1147,18 @@ end;
 procedure TPasElement.ProcessHints(const ASemiColonPrefix: boolean; var AResult: string);
 var
   h: TPasMemberHint;
+  S : String;
 begin
   if Hints <> [] then
-  begin
+    begin
     if ASemiColonPrefix then
       AResult := AResult + ';';
-    for h := Low(TPasMemberHint) to High(TPasMemberHint) do
-    begin
-      if h in Hints then
-        AResult := AResult + ' ' + cPasMemberHint[h] + ';'
+    S:=HintsString;
+    if (S<>'') then
+      AResult:=AResult+' '+S;
+    if ASemiColonPrefix then
+      AResult:=AResult+';';
     end;
-  end;
 end;
 
 constructor TPasElement.Create(const AName: string; AParent: TPasElement);
@@ -1132,7 +1189,7 @@ begin
   p := Parent;
   while Assigned(p) and not p.InheritsFrom(TPasDeclarations) do
   begin
-    if (p.ClassType <> TPasOverloadedProc) and (Length(p.Name) > 0) then
+    if (not (p is TPasOverloadedProc)) and (Length(p.Name) > 0) then
       if Length(Result) > 0 then
         Result := p.Name + '.' + Result
       else
@@ -1149,7 +1206,7 @@ begin
   p := Parent;
   while Assigned(p) do
   begin
-    if (p.ClassType <> TPasOverloadedProc) and (Length(p.Name) > 0) then
+    if (Not (p is TPasOverloadedProc)) and (Length(p.Name) > 0) then
       if Length(Result) > 0 then
         Result := p.Name + '.' + Result
       else
@@ -1160,12 +1217,12 @@ end;
 
 function TPasElement.GetModule: TPasModule;
 begin
-  if ClassType = TPasPackage then
+  if self is  TPasPackage then
     Result := nil
   else
   begin
     Result := TPasModule(Self);
-    while Assigned(Result) and not (Result.ClassType = TPasModule) do
+    while Assigned(Result) and not (Result is TPasModule) do
       Result := TPasModule(Result.Parent);
   end;
 end;
@@ -1187,14 +1244,14 @@ end;
 constructor TPasDeclarations.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Declarations := TList.Create;
-  ResStrings := TList.Create;
-  Types := TList.Create;
-  Consts := TList.Create;
-  Classes := TList.Create;
-  Functions := TList.Create;
-  Variables := TList.Create;
-  Properties := TList.Create;
+  Declarations := TFPList.Create;
+  ResStrings := TFPList.Create;
+  Types := TFPList.Create;
+  Consts := TFPList.Create;
+  Classes := TFPList.Create;
+  Functions := TFPList.Create;
+  Variables := TFPList.Create;
+  Properties := TFPList.Create;
 end;
 
 destructor TPasDeclarations.Destroy;
@@ -1231,7 +1288,7 @@ begin
     inherited Create('#' + AName, AParent)
   else
     inherited Create(AName, AParent);
-  Modules := TList.Create;
+  Modules := TFPList.Create;
 end;
 
 destructor TPasPackage.Destroy;
@@ -1279,7 +1336,7 @@ end;
 constructor TPasEnumType.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Values := TList.Create;
+  Values := TFPList.Create;
 end;
 
 destructor TPasEnumType.Destroy;
@@ -1332,7 +1389,7 @@ end;
 constructor TPasRecordType.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Members := TList.Create;
+  Members := TFPList.Create;
 end;
 
 destructor TPasRecordType.Destroy;
@@ -1360,12 +1417,14 @@ end;
 constructor TPasClassType.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  IsPacked := False;                     // 12/04/04 - Dave - Added
+  PackMode:=pmNone;                     // 12/04/04 - Dave - Added
   IsShortDefinition := False;
-  Members := TList.Create;
+  Members := TFPList.Create;
   Modifiers := TStringList.Create;
-  ClassVars := TList.Create;
-  Interfaces:= TList.Create;
+  ClassVars := TFPList.Create;
+  Interfaces:= TFPList.Create;
+  GenericTemplateTypes:=TFPList.Create;
+
 end;
 
 destructor TPasClassType.Destroy;
@@ -1380,6 +1439,9 @@ begin
   Modifiers.Free;
   ClassVars.Free;
   Interfaces.Free;
+  for i := 0 to GenericTemplateTypes.Count - 1 do
+    TPasElement(GenericTemplateTypes[i]).Release;
+  GenericTemplateTypes.Free;
   inherited Destroy;
 end;
 
@@ -1395,7 +1457,7 @@ end;
 constructor TPasProcedureType.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Args := TList.Create;
+  Args := TFPList.Create;
 end;
 
 destructor TPasProcedureType.Destroy;
@@ -1465,7 +1527,7 @@ end;
 constructor TPasProperty.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Args := TList.Create;
+  Args := TFPList.Create;
 end;
 
 destructor TPasProperty.Destroy;
@@ -1482,7 +1544,7 @@ end;
 constructor TPasOverloadedProc.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Overloads := TList.Create;
+  Overloads := TFPList.Create;
 end;
 
 destructor TPasOverloadedProc.Destroy;
@@ -1503,6 +1565,18 @@ begin
     SetLength(Result, 0);
 end;
 
+function TPasProcedure.GetCallingConvention: TCallingConvention;
+begin
+  Result:=ccDefault;
+  if Assigned(ProcType) then
+    Result:=ProcType.CallingConvention;
+end;
+
+procedure TPasProcedure.SetCallingConvention(AValue: TCallingConvention);
+begin
+  if Assigned(ProcType) then
+    ProcType.CallingConvention:=AValue;
+end;
 
 destructor TPasProcedure.Destroy;
 begin
@@ -1521,7 +1595,7 @@ end;
 constructor TPasProcedureImpl.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Locals := TList.Create;
+  Locals := TFPList.Create;
 end;
 
 destructor TPasProcedureImpl.Destroy;
@@ -1617,7 +1691,7 @@ end;
 constructor TPasImplBlock.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Elements := TList.Create;
+  Elements := TFPList.Create;
 end;
 
 destructor TPasImplBlock.Destroy;
@@ -1777,37 +1851,75 @@ end;
 
 function TPasResString.GetDeclaration (full : boolean) : string;
 begin
-  Result:=Value;
+  Result:=Expr.GetDeclaration(true);
   If Full Then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
+end;
+
+destructor TPasResString.Destroy;
+begin
+  If Assigned(Expr) then
+    Expr.Release;
+  inherited Destroy;
 end;
 
 function TPasPointerType.GetDeclaration (full : boolean) : string;
 begin
   Result:='^'+DestType.Name;
   If Full then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
 end;
 
 function TPasAliasType.GetDeclaration (full : boolean) : string;
 begin
   Result:=DestType.Name;
   If Full then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
 end;
 
 function TPasClassOfType.GetDeclaration (full : boolean) : string;
 begin
   Result:='Class of '+DestType.Name;
   If Full then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
 end;
 
 function TPasRangeType.GetDeclaration (full : boolean) : string;
 begin
   Result:=RangeStart+'..'+RangeEnd;
   If Full then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
+end;
+
+destructor TPasRangeType.Destroy;
+begin
+  FreeAndNil(RangeExpr);
+  inherited Destroy;
+end;
+
+function TPasRangeType.RangeStart: String;
+begin
+  Result:=RangeExpr.Left.GetDeclaration(False);
+end;
+
+function TPasRangeType.RangeEnd: String;
+begin
+  Result:=RangeExpr.Right.GetDeclaration(False);
 end;
 
 function TPasArrayType.GetDeclaration (full : boolean) : string;
@@ -1823,7 +1935,15 @@ begin
   else
     Result:=Result+'const';
   If Full Then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
+end;
+
+function TPasArrayType.IsPacked: Boolean;
+begin
+  Result:=PackMode=pmPacked;
 end;
 
 function TPasFileType.GetDeclaration (full : boolean) : string;
@@ -1832,7 +1952,10 @@ begin
   If Assigned(Eltype) then
     Result:=Result+' of '+ElType.Name;
   If Full Then
+    begin
     Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
 end;
 
 Function IndentStrings(S : TStrings; indent : Integer) : string;
@@ -1876,6 +1999,8 @@ begin
       Result:=IndentStrings(S,Length(Name)+4)
     else
       Result:=IndentStrings(S,1);
+    if Full then
+      ProcessHints(False,Result);
   finally
     S.Free;
   end;
@@ -1888,7 +2013,7 @@ Var
   i : Integer;
 
 begin
-  If EnumType is TPasEnumType then
+  If (EnumType is TPasEnumType) and (EnumType.Name='') then
     begin
     S:=TStringList.Create;
     Try
@@ -1910,6 +2035,8 @@ begin
     If Full then
       Result:=Name+' = '+Result;
     end;
+  If Full then
+    ProcessHints(False,Result);
 end;
 
 function TPasRecordType.GetDeclaration (full : boolean) : string;
@@ -1956,6 +2083,16 @@ begin
   end;
 end;
 
+function TPasRecordType.IsPacked: Boolean;
+begin
+  Result:=(PackMode <> pmNone);
+end;
+
+function TPasRecordType.IsBitPacked: Boolean;
+begin
+  Result:=(PackMode=pmBitPacked)
+end;
+
 procedure TPasProcedureType.GetArguments(List : TStrings);
 
 Var
@@ -2037,6 +2174,9 @@ function TPasVariable.GetDeclaration (full : boolean) : string;
 Const
  Seps : Array[Boolean] of Char = ('=',':');
 
+Var
+  H : TPasMemberHint;
+  B : Boolean;
 begin
   if (Value = '') and Assigned(Expr) then
     Value := Expr.GetDeclaration(full);
@@ -2053,7 +2193,10 @@ begin
   else
     Result:=Value;
   If Full then
+    begin
     Result:=Name+' '+Seps[Assigned(VarType)]+' '+Result;
+    Result:=Result+HintsString;
+    end;
 end;
 
 function TPasProperty.GetDeclaration (full : boolean) : string;
@@ -2315,7 +2458,7 @@ end;
 constructor TPasSection.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  UsesList := TList.Create;
+  UsesList := TFPList.Create;
 end;
 
 destructor TPasSection.Destroy;
@@ -2339,7 +2482,7 @@ end;
 constructor TProcedureBody.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
-  Labels:=TList.Create;
+  Labels:=TFPList.Create;
 end;
 
 destructor TProcedureBody.Destroy;

Різницю між файлами не показано, бо вона завелика
+ 638 - 291
packages/fcl-passrc/src/pparser.pp


Різницю між файлами не показано, бо вона завелика
+ 675 - 131
packages/fcl-passrc/src/pscanner.pp


+ 1336 - 0
packages/fcl-passrc/tests/tcscanner.pas

@@ -0,0 +1,1336 @@
+unit tcscanner;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, typinfo, fpcunit, testutils, testregistry, pscanner, pparser;
+
+type
+
+  { TTestTokenFinder }
+
+  TTestTokenFinder = class(TTestCase)
+  Published
+    Procedure TestFind;
+  end;
+
+  { TTestStreamLineReader }
+
+
+  TTestStreamLineReader = class(TTestCase)
+  Private
+    FReader: TStreamLineReader;
+  Protected
+    procedure NewSource(Const Source : string);
+    Procedure TestLine(Const ALine : String; ExpectEOF : Boolean = True);
+    procedure TearDown; override;
+  Published
+    Procedure TestCreate;
+    Procedure TestEOF;
+    Procedure TestEmptyLine;
+    Procedure TestEmptyLineCR;
+    Procedure TestEmptyLineLF;
+    Procedure TestEmptyLineCRLF;
+    Procedure TestEmptyLineLFCR;
+    Procedure TestOneLine;
+    Procedure TestTwoLines;
+  end;
+
+  { TTestingPascalScanner }
+
+  TTestingPascalScanner = Class(TPascalScanner)
+  private
+    FDoSpecial: Boolean;
+  protected
+    function HandleMacro(AIndex: integer): TToken;override;
+  Public
+    Property DoSpecial : Boolean Read FDoSpecial Write FDoSpecial;
+  end;
+
+  { TTestScanner }
+  TTestScanner= class(TTestCase)
+  Private
+    FLI: String;
+    FScanner : TPascalScanner;
+    FResolver : TStreamResolver;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Function TokenToString(tk : TToken) : string;
+    Procedure AssertEquals(Msg : String; Expected,Actual : TToken); overload;
+    procedure NewSource(Const Source : string; DoClear : Boolean = True);
+    Procedure DoTestToken(t : TToken; Const ASource : String; Const CheckEOF : Boolean = True);
+    Procedure TestToken(t : TToken; Const ASource : String; Const CheckEOF : Boolean = True);
+    Procedure TestTokens(t : array of TToken; Const ASource : String; Const CheckEOF : Boolean = True;Const DoClear : Boolean = True);
+    Property LastIDentifier : String Read FLI Write FLi;
+  published
+    procedure TestEOF;
+    procedure TestWhitespace;
+    procedure TestComment1;
+    procedure TestComment2;
+    procedure TestComment3;
+    procedure TestNestedComment1;
+    procedure TestNestedComment2;
+    procedure TestNestedComment3;
+    procedure TestNestedComment4;
+    procedure TestIdentifier;
+    procedure TestString;
+    procedure TestNumber;
+    procedure TestChar;
+    procedure TestBraceOpen;
+    procedure TestBraceClose;
+    procedure TestMul;
+    procedure TestPlus;
+    procedure TestComma;
+    procedure TestMinus;
+    procedure TestDot;
+    procedure TestDivision;
+    procedure TestColon;
+    procedure TestSemicolon;
+    procedure TestLessThan;
+    procedure TestEqual;
+    procedure TestGreaterThan;
+    procedure TestAt;
+    procedure TestSquaredBraceOpen;
+    procedure TestSquaredBraceClose;
+    procedure TestCaret;
+    procedure TestBackslash;
+    procedure TestDotDot;
+    procedure TestAssign;
+    procedure TestNotEqual;
+    procedure TestLessEqualThan;
+    procedure TestGreaterEqualThan;
+    procedure TestPower;
+    procedure TestSymmetricalDifference;
+    procedure TestAbsolute;
+    procedure TestAnd;
+    procedure TestArray;
+    procedure TestAs;
+    procedure TestAsm;
+    procedure TestBegin;
+    procedure TestBitpacked;
+    procedure TestCase;
+    procedure TestClass;
+    procedure TestConst;
+    procedure TestConstructor;
+    procedure TestDestructor;
+    procedure TestDiv;
+    procedure TestDo;
+    procedure TestDownto;
+    procedure TestElse;
+    procedure TestEnd;
+    procedure TestExcept;
+    procedure TestExports;
+    procedure TestFalse;
+    procedure TestFile;
+    procedure TestFinalization;
+    procedure TestFinally;
+    procedure TestFor;
+    procedure TestFunction;
+    procedure TestGeneric;
+    procedure TestGoto;
+    procedure TestIf;
+    procedure TestImplementation;
+    procedure TestIn;
+    procedure TestInherited;
+    procedure TestInitialization;
+    procedure TestInline;
+    procedure TestInterface;
+    procedure TestIs;
+    procedure TestLabel;
+    procedure TestLibrary;
+    procedure TestMod;
+    procedure TestNil;
+    procedure TestNot;
+    procedure TestObject;
+    procedure TestOf;
+    procedure TestOn;
+    procedure TestOperator;
+    procedure TestOr;
+    procedure TestPacked;
+    procedure TestProcedure;
+    procedure TestProgram;
+    procedure TestProperty;
+    procedure TestRaise;
+    procedure TestRecord;
+    procedure TestRepeat;
+    procedure TestResourceString;
+    procedure TestSelf;
+    procedure TestSet;
+    procedure TestShl;
+    procedure TestShr;
+    procedure TestSpecialize;
+    procedure TestThen;
+    procedure TestThreadvar;
+    procedure TestTo;
+    procedure TestTrue;
+    procedure TestTry;
+    procedure TestType;
+    procedure TestUnit;
+    procedure TestUntil;
+    procedure TestUses;
+    procedure TestVar;
+    procedure TestWhile;
+    procedure TestWith;
+    procedure TestXor;
+    procedure TestLineEnding;
+    procedure TestTab;
+    Procedure TestTokenSeries;
+    Procedure TestTokenSeriesNoWhiteSpace;
+    Procedure TestTokenSeriesComments;
+    Procedure TestTokenSeriesNoComments;
+    Procedure TestDefine1;
+    Procedure TestDefine2;
+    Procedure TestDefine3;
+    Procedure TestDefine4;
+    Procedure TestDefine5;
+    Procedure TestDefine6;
+    Procedure TestDefine7;
+    Procedure TestDefine8;
+    Procedure TestDefine9;
+    Procedure TestDefine10;
+    Procedure TestDefine11;
+    Procedure TestDefine12;
+    Procedure TestInclude;
+    Procedure TestInclude2;
+    Procedure TestMacro1;
+    procedure TestMacro2;
+    procedure TestMacro3;
+    procedure TestMacroHandling;
+  end;
+
+implementation
+
+{ TTestingPascalScanner }
+
+function TTestingPascalScanner.HandleMacro(AIndex: integer): TToken;
+begin
+  if DoSpecial then
+    begin
+    Result:=tkIdentifier;
+    SetCurTokenstring('somethingweird');
+    end
+  else
+    Result:=inherited HandleMacro(AIndex);
+end;
+
+{ TTestTokenFinder }
+
+procedure TTestTokenFinder.TestFind;
+
+Var
+  tk,tkr : TToken;
+  S : string;
+  B : Boolean;
+
+begin
+  For tk:=tkAbsolute to tkXor do
+    begin
+    S:=tokenInfos[tk];
+    B:=IsNamedToken(S,tkr);
+    AssertEquals('Token '+S+' is a token',true,B);
+    AssertEquals('Token '+S+' returns correct token',Ord(tk),Ord(tkr));
+    end;
+end;
+
+{ TTestStreamLineReader }
+
+procedure TTestStreamLineReader.NewSource(Const Source: string);
+begin
+  FReader:=TStringStreamLineReader.Create('afile',Source);
+end;
+
+procedure TTestStreamLineReader.TestLine(const ALine: String; ExpectEOF: Boolean);
+begin
+  AssertNotNull('Have reader',FReader);
+  AssertEquals('Reading source line',ALine,FReader.ReadLine);
+  if ExpectEOF then
+    AssertEquals('End of file reached',True,FReader.IsEOF);
+end;
+
+procedure TTestStreamLineReader.TearDown;
+begin
+  inherited TearDown;
+  If Assigned(FReader) then
+    FreeAndNil(Freader);
+end;
+
+procedure TTestStreamLineReader.TestCreate;
+begin
+  FReader:=TStreamLineReader.Create('afile');
+  AssertEquals('Correct filename','afile',FReader.FileName);
+  AssertEquals('Initially empty',True,FReader.isEOF);
+end;
+
+procedure TTestStreamLineReader.TestEOF;
+begin
+  NewSource('');
+  AssertEquals('Empty stream',True,FReader.IsEOF);
+end;
+
+procedure TTestStreamLineReader.TestEmptyLine;
+begin
+  NewSource('');
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineCR;
+begin
+  NewSource(#13);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineLF;
+begin
+  NewSource(#10);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineCRLF;
+begin
+  NewSource(#13#10);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineLFCR;
+begin
+  NewSource(#10#13);
+  TestLine('',False);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestOneLine;
+
+Const
+    S = 'a line with text';
+begin
+  NewSource(S);
+  TestLine(S);
+end;
+
+procedure TTestStreamLineReader.TestTwoLines;
+Const
+    S = 'a line with text';
+begin
+  NewSource(S+sLineBreak+S);
+  TestLine(S,False);
+  TestLine(S);
+end;
+
+{ ---------------------------------------------------------------------
+  TTestScanner
+  ---------------------------------------------------------------------}
+
+procedure TTestScanner.SetUp;
+begin
+  FResolver:=TStreamResolver.Create;
+  FResolver.OwnsStreams:=True;
+  FScanner:=TTestingPascalScanner.Create(FResolver);
+  // Do nothing
+end; 
+
+procedure TTestScanner.TearDown; 
+begin
+  FreeAndNil(FScanner);
+  FreeAndNil(FResolver);
+end;
+
+function TTestScanner.TokenToString(tk: TToken): string;
+begin
+  Result:=GetEnumName(TypeInfo(TToken),Ord(tk));
+end;
+
+procedure TTestScanner.AssertEquals(Msg: String; Expected, Actual: TToken);
+begin
+  AssertEquals(Msg,TokenToString(Expected),TokenToString(Actual));
+end;
+
+procedure TTestScanner.NewSource(const Source: string; DoClear : Boolean = True);
+begin
+  if DoClear then
+    FResolver.Clear;
+  FResolver.AddStream('afile.pp',TStringStream.Create(Source));
+  FScanner.OpenFile('afile.pp');
+end;
+
+procedure TTestScanner.DoTestToken(t: TToken; const ASource: String;
+  Const CheckEOF: Boolean);
+
+Var
+  tk : ttoken;
+
+begin
+  NewSource(ASource);
+  tk:=FScanner.FetchToken;
+  AssertEquals('Read token equals expected token.',t,tk);
+  if CheckEOF then
+    begin
+    tk:=FScanner.FetchToken;
+    if (tk=tkLineEnding) and not (t in [tkEOF,tkLineEnding]) then
+      tk:=FScanner.FetchToken;
+    AssertEquals('EOF reached.',tkEOF,FScanner.FetchToken);
+    end;
+end;
+
+procedure TTestScanner.TestToken(t: TToken; const ASource: String; Const CheckEOF: Boolean);
+Var
+  S : String;
+begin
+  DoTestToken(t,ASource);
+  if (ASource<>'') then
+    begin
+    S:=ASource;
+    S[1]:=Upcase(S[1]);
+    DoTestToken(t,S);
+    end;
+  DoTestToken(t,UpperCase(ASource));
+  DoTestToken(t,LowerCase(ASource));
+end;
+
+procedure TTestScanner.TestTokens(t: array of TToken; const ASource: String;
+  const CheckEOF: Boolean;Const DoClear : Boolean = True);
+Var
+  tk : ttoken;
+  i : integer;
+
+begin
+  NewSource(ASource,DoClear);
+  For I:=Low(t) to High(t) do
+    begin
+    tk:=FScanner.FetchToken;
+    AssertEquals(Format('Read token %d equals expected token.',[i]),t[i],tk);
+    if tk=tkIdentifier then
+      LastIdentifier:=FScanner.CurtokenString;
+    end;
+  if CheckEOF then
+    begin
+    tk:=FScanner.FetchToken;
+    if (tk=tkLineEnding) then
+      tk:=FScanner.FetchToken;
+    AssertEquals('EOF reached.',tkEOF,FScanner.FetchToken);
+    end;
+end;
+
+procedure TTestScanner.TestEOF;
+begin
+  TestToken(tkEOF,'')
+end;
+
+procedure TTestScanner.TestWhitespace;
+
+begin
+  TestToken(tkWhitespace,' ');
+  TestToken(tkWhitespace,' ');
+end;
+
+
+procedure TTestScanner.TestComment1;
+
+begin
+  TestToken(tkComment,'{ comment }');
+end;
+
+
+procedure TTestScanner.TestComment2;
+
+begin
+  TestToken(tkComment,'(* comment *)');
+end;
+
+
+procedure TTestScanner.TestComment3;
+
+begin
+  TestToken(tkComment,'//');
+end;
+
+procedure TTestScanner.TestNestedComment1;
+begin
+  TestToken(tkComment,'// { comment } ');
+end;
+
+procedure TTestScanner.TestNestedComment2;
+begin
+  TestToken(tkComment,'(* { comment } *)');
+end;
+
+procedure TTestScanner.TestNestedComment3;
+begin
+  TestToken(tkComment,'{ { comment } }');
+end;
+
+procedure TTestScanner.TestNestedComment4;
+begin
+  TestToken(tkComment,'{ (* comment *) }');
+end;
+
+
+procedure TTestScanner.TestIdentifier;
+
+begin
+  TestToken(tkIdentifier,'identifier');
+end;
+
+
+procedure TTestScanner.TestString;
+
+begin
+  TestToken(pscanner.tkString,'''A string''');
+end;
+
+
+procedure TTestScanner.TestNumber;
+
+begin
+  TestToken(tkNumber,'123');
+end;
+
+
+procedure TTestScanner.TestChar;
+
+begin
+  TestToken(pscanner.tkChar,'#65 ', false);
+end;
+
+
+procedure TTestScanner.TestBraceOpen;
+
+begin
+  TestToken(tkBraceOpen,'(');
+end;
+
+
+procedure TTestScanner.TestBraceClose;
+
+begin
+  TestToken(tkBraceClose,')');
+end;
+
+
+procedure TTestScanner.TestMul;
+
+begin
+  TestToken(tkMul,'*');
+end;
+
+
+procedure TTestScanner.TestPlus;
+
+begin
+  TestToken(tkPlus,'+');
+end;
+
+
+procedure TTestScanner.TestComma;
+
+begin
+  TestToken(tkComma,',');
+end;
+
+
+procedure TTestScanner.TestMinus;
+
+begin
+  TestToken(tkMinus,'-');
+end;
+
+
+procedure TTestScanner.TestDot;
+
+begin
+  TestToken(tkDot,'.');
+end;
+
+
+procedure TTestScanner.TestDivision;
+
+begin
+  TestToken(tkDivision,'/');
+end;
+
+
+procedure TTestScanner.TestColon;
+
+begin
+  TestToken(tkColon,':');
+end;
+
+
+procedure TTestScanner.TestSemicolon;
+
+begin
+  TestToken(tkSemicolon,';');
+end;
+
+
+procedure TTestScanner.TestLessThan;
+
+begin
+  TestToken(tkLessThan,'<');
+end;
+
+
+procedure TTestScanner.TestEqual;
+
+begin
+  TestToken(tkEqual,'=');
+end;
+
+
+procedure TTestScanner.TestGreaterThan;
+
+begin
+  TestToken(tkGreaterThan,'>');
+end;
+
+
+procedure TTestScanner.TestAt;
+
+begin
+  TestToken(tkAt,'@');
+end;
+
+
+procedure TTestScanner.TestSquaredBraceOpen;
+
+begin
+  TestToken(tkSquaredBraceOpen,'[');
+end;
+
+
+procedure TTestScanner.TestSquaredBraceClose;
+
+begin
+  TestToken(tkSquaredBraceClose,']');
+end;
+
+
+procedure TTestScanner.TestCaret;
+
+begin
+  TestToken(tkCaret,'^');
+end;
+
+
+procedure TTestScanner.TestBackslash;
+
+begin
+  TestToken(tkBackslash,'\');
+end;
+
+
+procedure TTestScanner.TestDotDot;
+
+begin
+  TestToken(tkDotDot,'..');
+end;
+
+
+procedure TTestScanner.TestAssign;
+
+begin
+  TestToken(tkAssign,':=');
+end;
+
+
+procedure TTestScanner.TestNotEqual;
+
+begin
+  TestToken(tkNotEqual,'<>');
+end;
+
+
+procedure TTestScanner.TestLessEqualThan;
+
+begin
+  TestToken(tkLessEqualThan,'<=');
+end;
+
+
+procedure TTestScanner.TestGreaterEqualThan;
+
+begin
+  TestToken(tkGreaterEqualThan,'>=');
+end;
+
+
+procedure TTestScanner.TestPower;
+
+begin
+  TestToken(tkPower,'**');
+end;
+
+
+procedure TTestScanner.TestSymmetricalDifference;
+
+begin
+  TestToken(tkSymmetricalDifference,'><');
+end;
+
+
+procedure TTestScanner.TestAbsolute;
+
+begin
+  TestToken(tkabsolute,'absolute');
+end;
+
+
+procedure TTestScanner.TestAnd;
+
+begin
+  TestToken(tkand,'and');
+end;
+
+
+procedure TTestScanner.TestArray;
+
+begin
+  TestToken(tkarray,'array');
+end;
+
+
+procedure TTestScanner.TestAs;
+
+begin
+  TestToken(tkas,'as');
+end;
+
+
+procedure TTestScanner.TestAsm;
+
+begin
+  TestToken(tkasm,'asm');
+end;
+
+
+procedure TTestScanner.TestBegin;
+
+begin
+  TestToken(tkbegin,'begin');
+end;
+
+
+procedure TTestScanner.TestBitpacked;
+
+begin
+  TestToken(tkbitpacked,'bitpacked');
+end;
+
+
+procedure TTestScanner.TestCase;
+
+begin
+  TestToken(tkcase,'case');
+end;
+
+
+procedure TTestScanner.TestClass;
+
+begin
+  TestToken(tkclass,'class');
+end;
+
+
+procedure TTestScanner.TestConst;
+
+begin
+  TestToken(tkconst,'const');
+end;
+
+
+procedure TTestScanner.TestConstructor;
+
+begin
+  TestToken(tkconstructor,'constructor');
+end;
+
+
+procedure TTestScanner.TestDestructor;
+
+begin
+  TestToken(tkdestructor,'destructor');
+end;
+
+
+procedure TTestScanner.TestDiv;
+
+begin
+  TestToken(tkdiv,'div');
+end;
+
+
+procedure TTestScanner.TestDo;
+
+begin
+  TestToken(tkdo,'do');
+end;
+
+
+procedure TTestScanner.TestDownto;
+
+begin
+  TestToken(tkdownto,'downto');
+end;
+
+
+procedure TTestScanner.TestElse;
+
+begin
+  TestToken(tkelse,'else');
+end;
+
+
+procedure TTestScanner.TestEnd;
+
+begin
+  TestToken(tkend,'end');
+end;
+
+
+procedure TTestScanner.TestExcept;
+
+begin
+  TestToken(tkexcept,'except');
+end;
+
+
+procedure TTestScanner.TestExports;
+
+begin
+  TestToken(tkexports,'exports');
+end;
+
+
+procedure TTestScanner.TestFalse;
+
+begin
+  TestToken(tkfalse,'false');
+end;
+
+
+procedure TTestScanner.TestFile;
+
+begin
+  TestToken(tkfile,'file');
+end;
+
+
+procedure TTestScanner.TestFinalization;
+
+begin
+  TestToken(tkfinalization,'finalization');
+end;
+
+
+procedure TTestScanner.TestFinally;
+
+begin
+  TestToken(tkfinally,'finally');
+end;
+
+
+procedure TTestScanner.TestFor;
+
+begin
+  TestToken(tkfor,'for');
+end;
+
+
+procedure TTestScanner.TestFunction;
+
+begin
+  TestToken(tkfunction,'function');
+end;
+
+
+procedure TTestScanner.TestGeneric;
+
+begin
+  TestToken(tkgeneric,'generic');
+end;
+
+
+procedure TTestScanner.TestGoto;
+
+begin
+  TestToken(tkgoto,'goto');
+end;
+
+
+procedure TTestScanner.TestIf;
+
+begin
+  TestToken(tkif,'if');
+end;
+
+
+procedure TTestScanner.TestImplementation;
+
+begin
+  TestToken(tkimplementation,'implementation');
+end;
+
+
+procedure TTestScanner.TestIn;
+
+begin
+  TestToken(tkin,'in');
+end;
+
+
+procedure TTestScanner.TestInherited;
+
+begin
+  TestToken(tkinherited,'inherited');
+end;
+
+
+procedure TTestScanner.TestInitialization;
+
+begin
+  TestToken(tkinitialization,'initialization');
+end;
+
+
+procedure TTestScanner.TestInline;
+
+begin
+  TestToken(tkinline,'inline');
+end;
+
+
+procedure TTestScanner.TestInterface;
+
+begin
+  TestToken(tkinterface,'interface');
+end;
+
+
+procedure TTestScanner.TestIs;
+
+begin
+  TestToken(tkis,'is');
+end;
+
+
+procedure TTestScanner.TestLabel;
+
+begin
+  TestToken(tklabel,'label');
+end;
+
+
+procedure TTestScanner.TestLibrary;
+
+begin
+  TestToken(tklibrary,'library');
+end;
+
+
+procedure TTestScanner.TestMod;
+
+begin
+  TestToken(tkmod,'mod');
+end;
+
+
+procedure TTestScanner.TestNil;
+
+begin
+  TestToken(tknil,'nil');
+end;
+
+
+procedure TTestScanner.TestNot;
+
+begin
+  TestToken(tknot,'not');
+end;
+
+
+procedure TTestScanner.TestObject;
+
+begin
+  TestToken(tkobject,'object');
+end;
+
+
+procedure TTestScanner.TestOf;
+
+begin
+  TestToken(tkof,'of');
+end;
+
+
+procedure TTestScanner.TestOn;
+
+begin
+  TestToken(tkon,'on');
+end;
+
+
+procedure TTestScanner.TestOperator;
+
+begin
+  TestToken(tkoperator,'operator');
+end;
+
+
+procedure TTestScanner.TestOr;
+
+begin
+  TestToken(tkor,'or');
+end;
+
+
+procedure TTestScanner.TestPacked;
+
+begin
+  TestToken(tkpacked,'packed');
+end;
+
+
+procedure TTestScanner.TestProcedure;
+
+begin
+  TestToken(tkprocedure,'procedure');
+end;
+
+
+procedure TTestScanner.TestProgram;
+
+begin
+  TestToken(tkprogram,'program');
+end;
+
+
+procedure TTestScanner.TestProperty;
+
+begin
+  TestToken(tkproperty,'property');
+end;
+
+
+procedure TTestScanner.TestRaise;
+
+begin
+  TestToken(tkraise,'raise');
+end;
+
+
+procedure TTestScanner.TestRecord;
+
+begin
+  TestToken(tkrecord,'record');
+end;
+
+
+procedure TTestScanner.TestRepeat;
+
+begin
+  TestToken(tkrepeat,'repeat');
+end;
+
+
+procedure TTestScanner.TestResourceString;
+
+begin
+  TestToken(tkResourceString,'resourcestring');
+end;
+
+
+procedure TTestScanner.TestSelf;
+
+begin
+  TestToken(tkself,'self');
+end;
+
+
+procedure TTestScanner.TestSet;
+
+begin
+  TestToken(tkset,'set');
+end;
+
+
+procedure TTestScanner.TestShl;
+
+begin
+  TestToken(tkshl,'shl');
+end;
+
+
+procedure TTestScanner.TestShr;
+
+begin
+  TestToken(tkshr,'shr');
+end;
+
+
+procedure TTestScanner.TestSpecialize;
+
+begin
+  TestToken(tkspecialize,'specialize');
+end;
+
+
+procedure TTestScanner.TestThen;
+
+begin
+  TestToken(tkthen,'then');
+end;
+
+
+procedure TTestScanner.TestThreadvar;
+
+begin
+  TestToken(tkthreadvar,'threadvar');
+end;
+
+
+procedure TTestScanner.TestTo;
+
+begin
+  TestToken(tkto,'to');
+end;
+
+
+procedure TTestScanner.TestTrue;
+
+begin
+  TestToken(tktrue,'true');
+end;
+
+
+procedure TTestScanner.TestTry;
+
+begin
+  TestToken(tktry,'try');
+end;
+
+
+procedure TTestScanner.TestType;
+
+begin
+  TestToken(tktype,'type');
+end;
+
+
+procedure TTestScanner.TestUnit;
+
+begin
+  TestToken(tkunit,'unit');
+end;
+
+
+procedure TTestScanner.TestUntil;
+
+begin
+  TestToken(tkuntil,'until');
+end;
+
+
+procedure TTestScanner.TestUses;
+
+begin
+  TestToken(tkuses,'uses');
+end;
+
+
+procedure TTestScanner.TestVar;
+
+begin
+  TestToken(tkvar,'var');
+end;
+
+
+procedure TTestScanner.TestWhile;
+
+begin
+  TestToken(tkwhile,'while');
+end;
+
+
+procedure TTestScanner.TestWith;
+
+begin
+  TestToken(tkwith,'with');
+end;
+
+
+procedure TTestScanner.TestXor;
+
+begin
+  TestToken(tkxor,'xor');
+end;
+
+
+procedure TTestScanner.TestLineEnding;
+
+begin
+  TestToken(tkLineEnding,#10);
+end;
+
+
+procedure TTestScanner.TestTab;
+
+begin
+  TestToken(tkTab,#9);
+end;
+
+procedure TTestScanner.TestTokenSeries;
+begin
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkthen,tkWhiteSpace,tkIdentifier],'in of then aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesNoWhiteSpace;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkin,tkOf,tkthen,tkIdentifier],'in of then aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesComments;
+begin
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkComment,tkWhiteSpace,tkIdentifier],'in of {then} aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesNoComments;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkWhiteSpace,tkIdentifier],'in of {then} aninteger')
+end;
+
+procedure TTestScanner.TestDefine1;
+begin
+  TestTokens([tkComment],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine2;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  TestTokens([tkComment,tkWhitespace,tkOf,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine3;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  TestTokens([tkComment,tkWhitespace,tkOf,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine4;
+begin
+  TestTokens([tkComment,tkWhitespace,tkin,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine5;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkLineEnding],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine6;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine7;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine8;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkin,tkWhitespace],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine9;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine10;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine11;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkOf],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine12;
+begin
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkin],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestInclude;
+begin
+  FResolver.AddStream('myinclude.inc',TStringStream.Create('if true then'));
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkIf,tkTrue,tkThen],'{$I myinclude.inc}',True,False);
+end;
+
+procedure TTestScanner.TestInclude2;
+begin
+  FResolver.AddStream('myinclude.inc',TStringStream.Create('if true then'));
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkIf,tkTrue,tkThen,tkElse],'{$I myinclude.inc} else',True,False);
+end;
+
+procedure TTestScanner.TestMacro1;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],'{$DEFINE MM:=begin end.}'#13#10'MM',True,False);
+end;
+
+procedure TTestScanner.TestMacro2;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],'{$DEFINE MM:=begin end}'#13#10'MM .',True,False);
+end;
+
+procedure TTestScanner.TestMacro3;
+begin
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkof],'{$DEFINE MM:=begin end}'#13#10'{$IFDEF MM} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestMacroHandling;
+begin
+  TTestingPascalScanner(FScanner).DoSpecial:=True;
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkIdentifier],'{$DEFINE MM:=begin end}'#13#10'MM');
+  AssertEQuals('Correct identifier', 'somethingweird',LastIdentifier);
+end;
+
+
+
+
+initialization
+  RegisterTests([TTestTokenFinder,TTestStreamLineReader,TTestScanner]);
+end.
+

+ 82 - 0
packages/fcl-passrc/tests/testpassrc.lpi

@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="testpassrc.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testpassrc"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="tcscanner.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcscanner"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+    </SearchPaths>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CompilerMessages>
+        <UseMsgFile Value="True"/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 25 - 0
packages/fcl-passrc/tests/testpassrc.lpr

@@ -0,0 +1,25 @@
+program testpassrc;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, tcscanner;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.

+ 149 - 139
utils/fpcm/fpcmake.inc

@@ -1,7 +1,7 @@
 {$ifdef Delphi}
-const fpcmakeini : array[0..215] of string[240]=(
+const fpcmakeini : array[0..216] of string[240]=(
 {$else Delphi}
-const fpcmakeini : array[0..215,1..240] of char=(
+const fpcmakeini : array[0..216,1..240] of char=(
 {$endif Delphi}
   ';'#010+
   '; Templates used by fpcmake to create a Makefile from Makefile.fpc'#010+
@@ -1202,16 +1202,26 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifndef CROSSBOOTSTRAP'#010+
   'ifneq ($(BINUTILSPREFIX),)'#010+
   'override FPCOP','T+=-XP$(BINUTILSPREFIX)'#010+
-  'override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)'#010+
   'endif'#010+
   'ifneq ($(BINUTILSPREFIX),)'#010+
   'override FPCOPT+=-Xr$(RLINKPATH)'#010+
   'endif'#010+
   'endif'#010+
   #010+
+  '# When BINUTILSPREFIX is given and we are not cross-compiling then use'+
+  #010+
+  '# it while compiling the fpmake file. (For example to build i386-f','re'+
+  'ebsd'#010+
+  '# with BINUTILSPREFIX=i386-)'#010+
+  'ifndef CROSSCOMPILE'#010+
+  'ifneq ($(BINUTILSPREFIX),)'#010+
+  'override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)'#010+
+  'endif'#010+
+  'endif'#010+
+  #010+
   '# User dirs should be first, so they are looked at first'#010+
   'ifdef UNITDIR'#010+
-  'override FPCOPT+=$(addpr','efix -Fu,$(UNITDIR))'#010+
+  'override FPCOPT+=$(addprefix -F','u,$(UNITDIR))'#010+
   'endif'#010+
   'ifdef LIBDIR'#010+
   'override FPCOPT+=$(addprefix -Fl,$(LIBDIR))'#010+
@@ -1224,7 +1234,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   '# Smartlinking'#010+
-  'ifdef LI','NKSMART'#010+
+  'ifdef LINKSMART',#010+
   'override FPCOPT+=-XX'#010+
   'endif'#010+
   #010+
@@ -1241,7 +1251,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '# Release mode'#010+
   '# (strip, optimize and don'#039't load fpc.cfg)'#010+
-  '# ','fpc 2.1 has -O2 for all targets'#010+
+  '# fpc 2.1',' has -O2 for all targets'#010+
   'ifdef RELEASE'#010+
   'ifneq ($(findstring 2.0.,$(FPC_VERSION)),)'#010+
   'ifeq ($(CPU_TARGET),i386)'#010+
@@ -1253,7 +1263,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'else'#010+
   'FPCCPUOPT:=-O2'#010+
   'endif'#010+
-  'override FPCOPT+=-Ur -Xs',' $(FPCCPUOPT) -n'#010+
+  'override FPCOPT+=-Ur -Xs $(FPCC','PUOPT) -n'#010+
   'override FPCOPTDEF+=RELEASE'#010+
   'endif'#010+
   #010+
@@ -1272,7 +1282,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'override FPCOPT+=-vwni'#010+
   'endif'#010+
   #010+
-  '# ','Needed compiler options'#010+
+  '# Needed ','compiler options'#010+
   'ifdef COMPILER_OPTIONS'#010+
   'override FPCOPT+=$(COMPILER_OPTIONS)'#010+
   'endif'#010+
@@ -1280,7 +1290,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))'#010+
   'endif'#010+
   'ifdef COMPILER_LIBRARYDIR'#010+
-  'override FPCOPT+=$(addprefix -Fl,$(COMPIL','ER_LIBRARYDIR))'#010+
+  'override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBR','ARYDIR))'#010+
   'endif'#010+
   'ifdef COMPILER_OBJECTDIR'#010+
   'override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))'#010+
@@ -1290,8 +1300,8 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   '# Cross compiler utils'#010+
-  'ifdef CROSSBINDIR'#010,
-  'override FPCOPT+=-FD$(CROSSBINDIR)'#010+
+  'ifdef CROSSBINDIR'#010+
+  'overrid','e FPCOPT+=-FD$(CROSSBINDIR)'#010+
   'endif'#010+
   #010+
   '# Target dirs and the prefix to use for clean/install'#010+
@@ -1300,7 +1310,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifeq ($(COMPILER_TARGETDIR),.)'#010+
   'override TARGETDIRPREFIX='#010+
   'else'#010+
-  'override TARGET','DIRPREFIX=$(COMPILER_TARGETDIR)/'#010+
+  'override TARGETDIRPREF','IX=$(COMPILER_TARGETDIR)/'#010+
   'endif'#010+
   'endif'#010+
   #010+
@@ -1310,7 +1320,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifeq ($(COMPILER_UNITTARGETDIR),.)'#010+
   'override UNITTARGETDIRPREFIX='#010+
   'else'#010+
-  'o','verride UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/'#010+
+  'override',' UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/'#010+
   'endif'#010+
   'else'#010+
   'ifdef COMPILER_TARGETDIR'#010+
@@ -1320,8 +1330,8 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   'ifdef CREATESHARED'#010+
-  'override FPCOPT','+=-Cg'#010+
-  #010+
+  'override FPCOPT+=-Cg'#010+
+  #010,
   'ifeq ($(CPU_TARGET),i386)'#010+
   'override FPCOPT+=-Aas'#010+
   'endif'#010+
@@ -1332,7 +1342,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifeq ($(findstring 2.0.,$(FPC_VERSION)),)'#010+
   'ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris)'+
   ',)'#010+
-  'ifeq ($(CPU_TARGET','),x86_64)'#010+
+  'ifeq ($(CPU_TARGET),x86_6','4)'#010+
   'override FPCOPT+=-Cg'#010+
   'endif'#010+
   'endif'#010+
@@ -1349,7 +1359,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'override FPCOPT+=-Fl$(GCCLIBDIR)'#010+
   'endif'#010+
   'ifdef OTHERLIBDIR'#010+
-  'o','verride FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR))'#010+
+  'override',' FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR))'#010+
   'endif'#010+
   #010+
   #010+
@@ -1361,7 +1371,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '# Add defines from FPCOPTDEF to FPCOPT'#010+
   'ifdef FPCOPTDEF'#010+
-  'override FPCOPT+=$(add','prefix -d,$(FPCOPTDEF))'#010+
+  'override FPCOPT+=$(addprefix ','-d,$(FPCOPTDEF))'#010+
   'endif'#010+
   #010+
   '# Was a config file specified ?'#010+
@@ -1373,7 +1383,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifdef USEENV'#010+
   'override FPCEXTCMD:=$(FPCOPT)'#010+
   'override FPCOPT:=!FPCEXTCMD'#010+
-  'expor','t FPCEXTCMD'#010+
+  'export FPCEX','TCMD'#010+
   'endif'#010+
   #010+
   'override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)'#010+
@@ -1385,9 +1395,9 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'ifdef ACROSSCOMPILE'#010+
   'override FPCOPT+=$(CROSSOPT)'#010+
-  'e','ndif'#010+
+  'endif'#010+
   #010+
-  '# Compiler commandline'#010+
+  '#',' Compiler commandline'#010+
   'override COMPILER:=$(FPC) $(FPCOPT)'#010+
   #010+
   '# also call ppas if with command option -s'#010+
@@ -1395,7 +1405,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifeq (,$(findstring -s ,$(COMPILER)))'#010+
   'EXECPPAS='#010+
   'else'#010+
-  'ifeq ($(FULL_SOURCE),$','(FULL_TARGET))'#010+
+  'ifeq ($(FULL_SOURCE),$(FULL_T','ARGET))'#010+
   'ifdef RUNBATCH'#010+
   'EXECPPAS:=@$(RUNBATCH) $(PPAS)'#010+
   'else'#010+
@@ -1408,7 +1418,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '[loaderrules]'#010+
   '#####################################################################'#010+
   '# Loaders'#010+
-  '#########################################','###########################'+
+  '################################################','####################'+
   '#'#010+
   #010+
   '.PHONY: fpc_loaders'#010+
@@ -1418,7 +1428,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'override CLEANTARGET+=fpc_loaders_clean'#010+
   'override INSTALLTARGET+=fpc_loaders_install'#010+
   #010+
-  'override LOADEROFILES:=$(addsuffix $(OEXT),$(','TARGET_LOADERS))'#010+
+  'override LOADEROFILES:=$(addsuffix $(OEXT),$(TARGET_','LOADERS))'#010+
   'endif'#010+
   #010+
   '%$(OEXT): %$(LOADEREXT)'#010+
@@ -1430,7 +1440,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_loaders: $(COMPILER_UNITTARGETDIR) $(LOADEROFILES)'#010+
   #010+
-  'fpc_loade','rs_clean:'#010+
+  'fpc_loaders_clea','n:'#010+
   'ifdef COMPILER_UNITTARGETDIR'#010+
   '        -$(DEL) $(addprefix $(COMPILER_UNITTARGETDIR)/,$(LOADEROFILES)'+
   ')'#010+
@@ -1440,18 +1450,17 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_loaders_install:'#010+
   '        $(MKDIR) $(INSTALL_UNITDIR)'#010+
-  'ifdef COMPILER_UNITTARGETDIR',#010+
-  '        $(INSTALL) $(addprefix $(COMPILER_UNITTARGETDIR)/,$(LOADEROFIL'+
-  'ES)) $(INSTALL_UNITDIR)'#010+
+  'ifdef COMPILER_UNITTARGETDIR'#010+
+  '      ','  $(INSTALL) $(addprefix $(COMPILER_UNITTARGETDIR)/,$(LOADEROF'+
+  'ILES)) $(INSTALL_UNITDIR)'#010+
   'else'#010+
   '        $(INSTALL) $(LOADEROFILES) $(INSTALL_UNITDIR)'#010+
   'endif'#010+
   #010+
   #010+
   '[unitrules]'#010+
-  '##################################################################','##'+
-  '#'#010+
-  '# Units'#010+
+  '#####################################################################'#010+
+  '# U','nits'#010+
   '#####################################################################'#010+
   #010+
   '.PHONY: fpc_units'#010+
@@ -1459,14 +1468,14 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifneq ($(TARGET_UNITS)$(TARGET_IMPLICITUNITS),)'#010+
   'override ALLTARGET+=fpc_units'#010+
   #010+
-  'override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS)',')'#010+
-  'override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITU'+
-  'NITS))'#010+
+  'override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))'#010+
+  'overr','ide IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICI'+
+  'TUNITS))'#010+
   'override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)'#010+
   'override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)'#010+
   'endif'#010+
   #010+
-  'fpc_units: $(COMPILER_UN','ITTARGETDIR) $(UNITPPUFILES)'#010+
+  'fpc_units: $(COMPILER_UNITTARGE','TDIR) $(UNITPPUFILES)'#010+
   #010+
   #010+
   '[exerules]'#010+
@@ -1476,25 +1485,25 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '.PHONY: fpc_exes'#010+
   #010+
-  '# Programs are not needed for a ','cross installation'#010+
+  '# Programs are not needed for a cross i','nstallation'#010+
   'ifndef CROSSINSTALL'#010+
   'ifneq ($(TARGET_PROGRAMS),)'#010+
   'override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS))'#010+
   'override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefi'+
-  'x $(STATICLIBPREFIX),$(addsuffix $(STATICLI','BEXT),$(TARGET_PROGRAMS))'+
+  'x $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$','(TARGET_PROGRAMS))'+
   ') $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_'+
   'PROGRAMS)))'#010+
   'override EXEDBGFILES:=$(addsuffix $(EXEDBGEXT),$(TARGET_PROGRAMS))'#010+
   #010+
   'override ALLTARGET+=fpc_exes'#010+
-  'override INSTALLEXEFILES+=$(EXEFILES',')'#010+
-  'override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)'#010+
+  'override INSTALLEXEFILES+=$(EXEFILES)'#010+
+  'overr','ide CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)'#010+
   'override CLEANEXEDBGFILES+=$(EXEDBGFILES)'#010+
   'ifeq ($(OS_TARGET),os2)'#010+
   'override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))'#010+
   'endif'#010+
   'ifeq ($(OS_TARGET),emx)'#010+
-  'override CLEANEXEFILES+=$(','addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))'#010+
+  'override CLEANEXEFILES+=$(addsuff','ix $(AOUTEXT),$(TARGET_PROGRAMS))'#010+
   'endif'#010+
   'endif'#010+
   'endif'#010+
@@ -1505,7 +1514,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '[rstrules]'#010+
   '#####################################################################'#010+
   '# Resource strings'#010+
-  '########','############################################################'+
+  '###############','#####################################################'+
   '#'#010+
   #010+
   'ifdef TARGET_RSTS'#010+
@@ -1516,7 +1525,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   #010+
   '[examplerules]'#010+
-  '###########################################','#########################'+
+  '##################################################','##################'+
   '#'#010+
   '# Examples'#010+
   '#####################################################################'#010+
@@ -1525,24 +1534,24 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'ifneq ($(TARGET_EXAMPLES),)'#010+
   'HASEXAMPLES=1'#010+
-  'override EXAMPLESOURCEFILES:=$(wildcard $(addsuffix .pp,$(TARGET_EX','A'+
-  'MPLES)) $(addsuffix .pas,$(TARGET_EXAMPLES)) $(addsuffix .lpr,$(TARGET'+
+  'override EXAMPLESOURCEFILES:=$(wildcard $(addsuffix .pp,$(TARGET_EXAMP'+
+  'LES)',') $(addsuffix .pas,$(TARGET_EXAMPLES)) $(addsuffix .lpr,$(TARGET'+
   '_EXAMPLES)) $(addsuffix .dpr,$(TARGET_EXAMPLES)))'#010+
   'override EXAMPLEFILES:=$(addsuffix $(EXEEXT),$(TARGET_EXAMPLES))'#010+
-  'override EXAMPLEOFILES:=$(addsuffix $(OEXT),$(TARGET_E','XAMPLES)) $(ad'+
+  'override EXAMPLEOFILES:=$(addsuffix $(OEXT),$(TARGET_EXAMPLES',')) $(ad'+
   'dprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_EXAMPL'+
   'ES))) $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TAR'+
   'GET_EXAMPLES)))'#010+
-  'override EXAMPLEDBGFILES:=$(addsuffix $(EXEDBGEXT),$(TARGET_EXAMPLES))',
+  'override EXAMPLEDBGFILES:=$(addsuffix $(EXEDBGEXT),$(TARGET_EXAMPLES))'+
   #010+
   #010+
-  'override CLEANEXEFILES+=$(EXAMPLEFILES) $(EXAMPLEOFILES)'#010+
+  'overr','ide CLEANEXEFILES+=$(EXAMPLEFILES) $(EXAMPLEOFILES)'#010+
   'override CLEANEXEDBGFILES+=$(EXAMPLEDBGFILES)'#010+
   'ifeq ($(OS_TARGET),os2)'#010+
   'override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))'#010+
   'endif'#010+
   'ifeq ($(OS_TARGET),emx)'#010+
-  'override CLEAN','EXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))'#010+
+  'override CLEANEXEFILE','S+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))'#010+
   'endif'#010+
   'endif'#010+
   'ifneq ($(TARGET_EXAMPLEDIRS),)'#010+
@@ -1554,7 +1563,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   #010+
   '[compilerules]'#010+
-  '################################','####################################'+
+  '#######################################','#############################'+
   '#'#010+
   '# General compile rules'#010+
   '#####################################################################'#010+
@@ -1562,7 +1571,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared'#010+
   #010+
   '$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)'#010+
-  '   ','     @$(ECHOREDIR) Compiled > $(FPCMADE)'#010+
+  '        @$','(ECHOREDIR) Compiled > $(FPCMADE)'#010+
   #010+
   'fpc_all: $(FPCMADE)'#010+
   #010+
@@ -1575,7 +1584,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_release:'#010+
   '        $(MAKE) all RELEASE=1'#010+
   #010+
-  '# General compile rules, available ','for both possible .pp and .pas ex'+
+  '# General compile rules, available for bot','h possible .pp and .pas ex'+
   'tensions'#010+
   #010+
   '.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res'#010+
@@ -1584,7 +1593,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)'#010+
   #010+
   '$(COMPILER_TARGETDIR):'#010+
-  '        $(MKDIRTREE) $(COMPILER','_TARGETDIR)'#010+
+  '        $(MKDIRTREE) $(COMPILER_TARGET','DIR)'#010+
   #010+
   '%$(PPUEXT): %.pp'#010+
   '        $(COMPILER) $<'#010+
@@ -1600,7 +1609,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '%$(EXEEXT): %.pas'#010+
   '        $(COMPILER) $<'#010+
-  '  ','      $(EXECPPAS)'#010+
+  '        $','(EXECPPAS)'#010+
   #010+
   '%$(EXEEXT): %.lpr'#010+
   '        $(COMPILER) $<'#010+
@@ -1614,18 +1623,18 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        windres -i $< -o $@'#010+
   #010+
   '# Search paths for .ppu, .pp, .pas, .lpr, .dpr'#010+
-  'vpath %.p','p $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)'#010+
+  'vpath %.pp $(COM','PILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)'#010+
   'vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)'#010+
   'vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)'#010+
   'vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)'#010+
-  'vpath %.inc $(COMPILER','_INCLUDEDIR)'#010+
+  'vpath %.inc $(COMPILER_INCLUD','EDIR)'#010+
   'vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)'#010+
   'vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)'#010+
   #010+
   '[sharedrules]'#010+
   '#####################################################################'#010+
   '# Library'#010+
-  '################################################','####################'+
+  '#######################################################','#############'+
   '#'#010+
   #010+
   '.PHONY: fpc_shared'#010+
@@ -1641,14 +1650,14 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   'ifndef SHARED_FULLNAME'#010+
-  'SHARE','D_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERS'+
+  'SHARED_FULLN','AME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERS'+
   'ION)$(SHAREDLIBEXT)'#010+
   'endif'#010+
   #010+
   '# Default sharedlib units are all unit objects'#010+
   'ifndef SHARED_LIBUNITS'#010+
   'SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)'#010+
-  'override SHARED_LIBUNIT','S:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED'+
+  'override SHARED_LIBUNITS:=$(fi','lter-out $(INSTALL_BUILDUNIT),$(SHARED'+
   '_LIBUNITS))'#010+
   'endif'#010+
   #010+
@@ -1656,7 +1665,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifdef HASSHAREDLIB'#010+
   '        $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1'#010+
   'ifneq ($(SHARED_BUILD),n)'#010+
-  '        $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNI','TTARGETDIR)'+
+  '        $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGET','DIR)'+
   ' -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)'#010+
   'endif'#010+
   'else'#010+
@@ -1666,7 +1675,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_shared_install:'#010+
   'ifneq ($(SHARED_BUILD),n)'#010+
   'ifneq ($(SHARED_LIBUNITS),)'#010+
-  'ifneq ($(wildcard $(COMPILER_UNITTARGET','DIR)/$(SHARED_FULLNAME)),)'#010+
+  'ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(','SHARED_FULLNAME)),)'#010+
   '        $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INST'+
   'ALL_SHAREDDIR)'#010+
   'endif'#010+
@@ -1676,7 +1685,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '[installrules]'#010+
   '#####################################################################'#010+
   '# Install rules'#010+
-  '########','############################################################'+
+  '###############','#####################################################'+
   '#'#010+
   #010+
   '.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall'#010+
@@ -1686,18 +1695,18 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   'ifdef INSTALL_BUILDUNIT'#010+
-  'ov','erride INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT)'+
+  'override ','INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT)'+
   ',$(INSTALLPPUFILES))'#010+
   'endif'#010+
   #010+
   'ifdef INSTALLPPUFILES'#010+
   'override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFI'+
-  'LES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT)',',$(STATICLIBEX'+
+  'LES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STAT','ICLIBEX'+
   'T),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEX'+
   'T),$(STATICLIBEXT),$(INSTALLPPUFILES)))'#010+
   'ifneq ($(UNITTARGETDIRPREFIX),)'#010+
   'override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir '+
-  '$(INSTALLPPUFI','LES)))'#010+
+  '$(INSTALLPPUFILES)))'#010,
   'override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPR'+
   'EFIX),$(notdir $(INSTALLPPULINKFILES))))'#010+
   'endif'#010+
@@ -1706,7 +1715,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   'ifdef INSTALLEXEFILES'#010+
-  'ifneq ($(TARGETDIR','PREFIX),)'#010+
+  'ifneq ($(TARGETDIRPREFIX)',',)'#010+
   'override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(IN'+
   'STALLEXEFILES)))'#010+
   'endif'#010+
@@ -1715,7 +1724,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_install: all $(INSTALLTARGET)'#010+
   'ifdef INSTALLEXEFILES'#010+
   '        $(MKDIR) $(INSTALL_BINDIR)'#010+
-  '        $(INSTALLEXE) $(INSTALLEXEFILES',') $(INSTALL_BINDIR)'#010+
+  '        $(INSTALLEXE) $(INSTALLEXEFILES) $(INS','TALL_BINDIR)'#010+
   'endif'#010+
   'ifdef INSTALL_CREATEPACKAGEFPC'#010+
   'ifdef FPCMAKE'#010+
@@ -1723,7 +1732,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'c,'#010+
   '# a safety check is done if Makefile.fpc is available'#010+
   'ifdef PACKAGE_VERSION'#010+
-  'ifneq ($(wildcard Ma','kefile.fpc),)'#010+
+  'ifneq ($(wildcard Makefile.','fpc),)'#010+
   '        $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc'#010+
   '        $(MKDIR) $(INSTALL_UNITDIR)'#010+
   '        $(INSTALL) Package.fpc $(INSTALL_UNITDIR)'#010+
@@ -1732,14 +1741,14 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   'endif'#010+
   'ifdef INSTALLPPUFILES'#010+
-  '        $(MKDIR) $(INSTALL_UNI','TDIR)'#010+
-  '        $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)'#010+
+  '        $(MKDIR) $(INSTALL_UNITDIR)'#010+
+  ' ','       $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)'#010+
   'ifneq ($(INSTALLPPULINKFILES),)'#010+
   '        $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)'#010+
   'endif'#010+
   'ifneq ($(wildcard $(LIB_FULLNAME)),)'#010+
   '        $(MKDIR) $(INSTALL_LIBDIR)'#010+
-  '      ','  $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)'#010+
+  '        $(INS','TALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)'#010+
   'ifdef inUnix'#010+
   '        ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)'#010+
   'endif'#010+
@@ -1747,7 +1756,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   'ifdef INSTALL_FILES'#010+
   '        $(MKDIR) $(INSTALL_DATADIR)'#010+
-  '        $(INSTALL) $(INSTALL_FILES) $(INSTALL','_DATADIR)'#010+
+  '        $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADI','R)'#010+
   'endif'#010+
   #010+
   'fpc_sourceinstall: distclean'#010+
@@ -1756,7 +1765,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))'#010+
   'ifdef HASEXAMPLES'#010+
-  '        $(MKDIR) ','$(INSTALL_EXAMPLEDIR)'#010+
+  '        $(MKDIR) $(INSTA','LL_EXAMPLEDIR)'#010+
   'endif'#010+
   'ifdef EXAMPLESOURCEFILES'#010+
   '        $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)'#010+
@@ -1766,7 +1775,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'AMPLEDIR)'#010+
   'endif'#010+
   #010+
-  '[distinst','allrules]'#010+
+  '[distinstallrule','s]'#010+
   '#####################################################################'#010+
   '# Dist Install'#010+
   '#####################################################################'#010+
@@ -1776,14 +1785,14 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_distinstall: install exampleinstall'#010+
   #010+
   #010+
-  '[zipins','tallrules]'#010+
+  '[zipinstallrul','es]'#010+
   '#####################################################################'#010+
   '# Zip'#010+
   '#####################################################################'#010+
   #010+
   '.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall'#010+
   #010+
-  '# Temporary pat','h to pack a file, can only use a single deep'#010+
+  '# Temporary path to pa','ck a file, can only use a single deep'#010+
   '# subdir, because the deltree can'#039't see the whole tree to remove'#010+
   'ifndef PACKDIR'#010+
   'ifndef inUnix'#010+
@@ -1793,7 +1802,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   'endif'#010+
   #010+
-  '# Maybe create default zipname',' from packagename'#010+
+  '# Maybe create default zipname from p','ackagename'#010+
   'ifndef ZIPNAME'#010+
   'ifdef DIST_ZIPNAME'#010+
   'ZIPNAME=$(DIST_ZIPNAME)'#010+
@@ -1808,7 +1817,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '# ZipTarget'#010+
   'ifndef ZIPTARGET'#010+
-  'ifd','ef DIST_ZIPTARGET'#010+
+  'ifdef DIST','_ZIPTARGET'#010+
   'ZIPTARGET=DIST_ZIPTARGET'#010+
   'else'#010+
   'ZIPTARGET=install'#010+
@@ -1825,9 +1834,9 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '# Use a wrapper script by default for Os/2'#010+
   'ifndef inUnix'#010+
   'USEZIPWRAPPER=1'#010+
-  'endif'#010,
+  'endif'#010+
   #010+
-  '# We need to be able to run in the current OS so fix'#010+
+  '# We n','eed to be able to run in the current OS so fix'#010+
   '# the path separator'#010+
   'ifdef USEZIPWRAPPER'#010+
   'ZIPPATHSEP=$(PATHSEP)'#010+
@@ -1836,13 +1845,13 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ZIPPATHSEP=/'#010+
   'endif'#010+
   #010+
-  '# Create commands to create ','the zip/tar file'#010+
+  '# Create commands to create the zip','/tar file'#010+
   'ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))'#010+
   'ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))'#010+
   'ifdef USETAR'#010+
   'ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)'#010+
-  'ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE)',' *'#010+
-  'else'#010+
+  'ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *'#010+
+  'else',#010+
   'ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)'#010+
   'ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDES'+
   'TFILE) *'#010+
@@ -1850,21 +1859,21 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_zipinstall:'#010+
   '        $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1'#010+
-  '        $','(MKDIR) $(DIST_DESTDIR)'#010+
+  '        $(MKDIR)',' $(DIST_DESTDIR)'#010+
   '        $(DEL) $(ZIPDESTFILE)'#010+
   'ifdef USEZIPWRAPPER'#010+
   '# Handle gecho separate as we need to espace \ with \\'#010+
   'ifneq ($(ECHOREDIR),echo)'#010+
   '        $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPE'+
   'R)'#010+
-  '        $(EC','HOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPE'+
+  '        $(ECHOREDIR',') -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPE'+
   'R)'#010+
   '        $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPP'+
   'ER)'#010+
   'else'#010+
   '        echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)'#010+
   '        echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)'#010+
-  '        echo',' $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)'#010+
+  '        echo $(ZIPC','MD_CDBASE) >> $(ZIPWRAPPER)'#010+
   'endif'#010+
   'ifdef inUnix'#010+
   '        /bin/sh $(ZIPWRAPPER)'#010+
@@ -1877,7 +1886,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   '        $(DEL) $(ZIPWRAPPER)'#010+
   'else'#010+
-  '        $(ZIPCMD_CDPACK) ; $(','ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)'#010+
+  '        $(ZIPCMD_CDPACK) ; $(ZIPCMD_','ZIP) ; $(ZIPCMD_CDBASE)'#010+
   'endif'#010+
   '        $(DELTREE) $(PACKDIR)'#010+
   #010+
@@ -1887,7 +1896,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_zipexampleinstall:'#010+
   'ifdef HASEXAMPLES'#010+
-  '        $(MAKE) fpc_zipi','nstall ZIPTARGET=exampleinstall ZIPSUFFIX=$('+
+  '        $(MAKE) fpc_zipinstall ','ZIPTARGET=exampleinstall ZIPSUFFIX=$('+
   'ZIPEXAMPLESUFFIX)'#010+
   'endif'#010+
   #010+
@@ -1897,23 +1906,24 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '[cleanrules]'#010+
   '#####################################################################'#010+
-  '# Clean rules',#010+
-  '#####################################################################'#010+
+  '# Clean rules'#010+
+  '######','##############################################################'+
+  '#'#010+
   #010+
   '.PHONY: fpc_clean fpc_cleanall fpc_distclean'#010+
   #010+
   'ifdef EXEFILES'#010+
   'override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES'+
   '))'#010+
-  'override CLEANEXEDBGFILES:=$(addpr','efix $(TARGETDIRPREFIX),$(CLEANEXE'+
+  'override CLEANEXEDBGFILES:=$(addprefix $(','TARGETDIRPREFIX),$(CLEANEXE'+
   'DBGFILES))'#010+
   'endif'#010+
   #010+
   'ifdef CLEAN_PROGRAMS'#010+
   'override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(E'+
   'XEEXT), $(CLEAN_PROGRAMS)))'#010+
-  'override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix',
-  ' $(EXEDBGEXT), $(CLEAN_PROGRAMS)))'#010+
+  'override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix '+
+  '$(EXED','BGEXT), $(CLEAN_PROGRAMS)))'#010+
   'endif'#010+
   #010+
   'ifdef CLEAN_UNITS'#010+
@@ -1922,13 +1932,13 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'ifdef CLEANPPUFILES'#010+
   'override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)'+
-  ') $(addprefix $(STATI','CLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$'+
+  ') $(addprefix $(STATICLIBPRE','FIX),$(subst $(PPUEXT),$(STATICLIBEXT),$'+
   '(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(S'+
   'TATICLIBEXT),$(CLEANPPUFILES)))'#010+
   'ifdef DEBUGSYMEXT'#010+
   'override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPP'+
-  'UFI','LES))'#010+
-  'endif'#010+
+  'UFILES))'#010+
+  'e','ndif'#010+
   'override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUF'+
   'ILES))'#010+
   'override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREF'+
@@ -1937,7 +1947,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_clean: $(CLEANTARGET)'#010+
   'ifdef CLEANEXEFILES'#010+
-  ' ','       -$(DEL) $(CLEANEXEFILES)'#010+
+  '        ','-$(DEL) $(CLEANEXEFILES)'#010+
   'endif'#010+
   '# DELTREE instead of DEL because on Mac OS X these are directories'#010+
   'ifdef CLEANEXEDBGFILES'#010+
@@ -1946,7 +1956,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'ifdef CLEANPPUFILES'#010+
   '        -$(DEL) $(CLEANPPUFILES)'#010+
   'endif'#010+
-  'ifneq (','$(CLEANPPULINKFILES),)'#010+
+  'ifneq ($(CLEAN','PPULINKFILES),)'#010+
   '        -$(DEL) $(CLEANPPULINKFILES)'#010+
   'endif'#010+
   'ifdef CLEANRSTFILES'#010+
@@ -1956,7 +1966,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        -$(DEL) $(CLEAN_FILES)'#010+
   'endif'#010+
   'ifdef LIB_NAME'#010+
-  '        -','$(DEL) $(LIB_NAME) $(LIB_FULLNAME)'#010+
+  '        -$(DEL) ','$(LIB_NAME) $(LIB_FULLNAME)'#010+
   'endif'#010+
   '        -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(F'+
   'PCEXTFILE) $(REDIRFILE)'#010+
@@ -1964,7 +1974,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   'fpc_cleanall: $(CLEANTARGET)'#010+
   'ifdef CLEANEXEFILES'#010+
-  '        -$','(DEL) $(CLEANEXEFILES)'#010+
+  '        -$(DEL) $','(CLEANEXEFILES)'#010+
   'endif'#010+
   'ifdef COMPILER_UNITTARGETDIR'#010+
   'ifdef CLEANPPUFILES'#010+
@@ -1974,7 +1984,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        -$(DEL) $(CLEANPPULINKFILES)'#010+
   'endif'#010+
   'ifdef CLEANRSTFILES'#010+
-  '        -$(DEL) $(addprefix $(','UNITTARGETDIRPREFIX),$(CLEANRSTFILES))'+
+  '        -$(DEL) $(addprefix $(UNITTAR','GETDIRPREFIX),$(CLEANRSTFILES))'+
   #010+
   'endif'#010+
   'endif'#010+
@@ -1984,7 +1994,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        -$(DELTREE) units'#010+
   '        -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIB'+
   'EXT) *$(SHAREDLIBEXT) *$(PPLEXT)'#010+
-  'ifneq',' ($(PPUEXT),.ppu)'#010+
+  'ifneq ($(PPU','EXT),.ppu)'#010+
   '        -$(DEL) *.o *.ppu *.a'#010+
   'endif'#010+
   '        -$(DELTREE) *$(SMARTEXT)'#010+
@@ -1992,7 +2002,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'CEXTFILE) $(REDIRFILE)'#010+
   '        -$(DEL) *_ppas$(BATCHEXT)'#010+
   'ifdef AOUTEXT'#010+
-  '        -$(D','EL) *$(AOUTEXT)'#010+
+  '        -$(DEL) *$(','AOUTEXT)'#010+
   'endif'#010+
   'ifdef DEBUGSYMEXT'#010+
   '        -$(DEL) *$(DEBUGSYMEXT)'#010+
@@ -2004,7 +2014,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '[baseinforules]'#010+
   '#####################################################################'#010+
   '# Base info rules'#010+
-  '###############################','#####################################'+
+  '######################################','##############################'+
   '#'#010+
   #010+
   '.PHONY: fpc_baseinfo'#010+
@@ -2015,94 +2025,94 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Package info =='#010+
   '        @$(ECHO)  Package Name..... $(PACKAGE_NAME)'#010+
-  '        @$(ECHO)  Packag','e Version.. $(PACKAGE_VERSION)'#010+
+  '        @$(ECHO)  Package Versi','on.. $(PACKAGE_VERSION)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Configuration info =='#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  FPC.......... $(FPC)'#010+
   '        @$(ECHO)  FPC Version.. $(FPC_VERSION)'#010+
-  '        @$(ECHO)  Source CPU... $(CPU_SOURCE)'#010,
-  '        @$(ECHO)  Target CPU... $(CPU_TARGET)'#010+
+  '        @$(ECHO)  Source CPU... $(CPU_SOURCE)'#010+
+  '       ',' @$(ECHO)  Target CPU... $(CPU_TARGET)'#010+
   '        @$(ECHO)  Source OS.... $(OS_SOURCE)'#010+
   '        @$(ECHO)  Target OS.... $(OS_TARGET)'#010+
   '        @$(ECHO)  Full Source.. $(FULL_SOURCE)'#010+
   '        @$(ECHO)  Full Target.. $(FULL_TARGET)'#010+
-  '        @$','(ECHO)  SourceSuffix. $(SOURCESUFFIX)'#010+
+  '        @$(ECHO) ',' SourceSuffix. $(SOURCESUFFIX)'#010+
   '        @$(ECHO)  TargetSuffix. $(TARGETSUFFIX)'#010+
   '        @$(ECHO)  FPC fpmake... $(FPCFPMAKE)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Directory info =='#010+
   '        @$(ECHO)'#010+
-  '        @$(ECHO)  Required pkgs... $','(REQUIRE_PACKAGES)'#010+
+  '        @$(ECHO)  Required pkgs... $(REQUIR','E_PACKAGES)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Basedir......... $(BASEDIR)'#010+
   '        @$(ECHO)  FPCDir.......... $(FPCDIR)'#010+
   '        @$(ECHO)  CrossBinDir..... $(CROSSBINDIR)'#010+
   '        @$(ECHO)  UnitsDir........ $(UNITSDIR)'#010+
-  '        @$(ECHO)','  PackagesDir..... $(PACKAGESDIR)'#010+
+  '        @$(ECHO)  Packa','gesDir..... $(PACKAGESDIR)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  GCC library..... $(GCCLIBDIR)'#010+
   '        @$(ECHO)  Other library... $(OTHERLIBDIR)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Tools info =='#010+
   '        @$(ECHO)'#010+
-  '        @$(ECHO)  As..','...... $(AS)'#010+
+  '        @$(ECHO)  As........ ','$(AS)'#010+
   '        @$(ECHO)  Ld........ $(LD)'#010+
   '        @$(ECHO)  Ar........ $(AR)'#010+
   '        @$(ECHO)  Rc........ $(RC)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Mv........ $(MVPROG)'#010+
   '        @$(ECHO)  Cp........ $(CPPROG)'#010+
-  '        @$(ECHO)  Rm.......','. $(RMPROG)'#010+
+  '        @$(ECHO)  Rm........ $(RMP','ROG)'#010+
   '        @$(ECHO)  GInstall.. $(GINSTALL)'#010+
   '        @$(ECHO)  Echo...... $(ECHO)'#010+
   '        @$(ECHO)  Shell..... $(SHELL)'#010+
   '        @$(ECHO)  Date...... $(DATE)'#010+
   '        @$(ECHO)  FPCMake... $(FPCMAKE)'#010+
-  '        @$(ECHO)  PPUMove... $(PPUM','OVE)'#010+
-  '        @$(ECHO)  Zip....... $(ZIPPROG)'#010+
+  '        @$(ECHO)  PPUMove... $(PPUMOVE)'#010+
+  '  ','      @$(ECHO)  Zip....... $(ZIPPROG)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Object info =='#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Target Loaders........ $(TARGET_LOADERS)'#010+
   '        @$(ECHO)  Target Units.......... $(TARGET_UNITS)'#010+
-  '        @','$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)'#010+
+  '        @$(ECHO)','  Target Implicit Units. $(TARGET_IMPLICITUNITS)'#010+
   '        @$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)'#010+
   '        @$(ECHO)  Target Dirs........... $(TARGET_DIRS)'#010+
   '        @$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)'#010+
-  '        ','@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)'#010+
+  '        @$(ECHO',')  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Clean Units......... $(CLEAN_UNITS)'#010+
   '        @$(ECHO)  Clean Files......... $(CLEAN_FILES)'#010+
   '        @$(ECHO)'#010+
-  '        @$(ECHO)  Install Units....... $(IN','STALL_UNITS)'#010+
+  '        @$(ECHO)  Install Units....... $(INSTALL_U','NITS)'#010+
   '        @$(ECHO)  Install Files....... $(INSTALL_FILES)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  == Install info =='#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  DateStr.............. $(DATESTR)'#010+
-  '        @$(ECHO)  ZipName.............. $(ZIPNAME',')'#010+
-  '        @$(ECHO)  ZipPrefix............ $(ZIPPREFIX)'#010+
+  '        @$(ECHO)  ZipName.............. $(ZIPNAME)'#010+
+  '     ','   @$(ECHO)  ZipPrefix............ $(ZIPPREFIX)'#010+
   '        @$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)'#010+
   '        @$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)'#010+
   '        @$(ECHO)  FullZipName.......... $(FULLZIPNAME)'#010+
-  '        @$(ECHO)  I','nstall FPC Package.. $(INSTALL_FPCPACKAGE)'#010+
+  '        @$(ECHO)  Install ','FPC Package.. $(INSTALL_FPCPACKAGE)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)'#010+
   '        @$(ECHO)  Install binary dir... $(INSTALL_BINDIR)'#010+
   '        @$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)'#010+
-  '     ','   @$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)'#010+
+  '        @$(E','CHO)  Install units dir.... $(INSTALL_UNITDIR)'#010+
   '        @$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)'#010+
   '        @$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)'#010+
   '        @$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)'#010+
-  '     ','   @$(ECHO)  Install data dir..... $(INSTALL_DATADIR)'#010+
+  '        @$(E','CHO)  Install data dir..... $(INSTALL_DATADIR)'#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Dist destination dir. $(DIST_DESTDIR)'#010+
   '        @$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)'#010+
   '        @$(ECHO)'#010+
   #010+
   '[inforules]'#010+
-  '###########################','#########################################'+
+  '##################################','##################################'+
   '#'#010+
   '# Info rules'#010+
   '#####################################################################'#010+
@@ -2112,7 +2122,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_info: $(INFORULES)'#010+
   #010+
   '[makefilerules]'#010+
-  '#######################################################','#############'+
+  '##############################################################','######'+
   '#'#010+
   '# Rebuild Makefile'#010+
   '#####################################################################'#010+
@@ -2122,7 +2132,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '        fpc_makefile_dirs'#010+
   #010+
   'fpc_makefile:'#010+
-  '        $(FPCMAKE) -w',' -T$(OS_TARGET) Makefile.fpc'#010+
+  '        $(FPCMAKE) -w -T$(OS','_TARGET) Makefile.fpc'#010+
   #010+
   'fpc_makefile_sub1:'#010+
   'ifdef TARGET_DIRS'#010+
@@ -2130,8 +2140,8 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'T_DIRS))'#010+
   'endif'#010+
   'ifdef TARGET_EXAMPLEDIRS'#010+
-  '        $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,','$(TAR'+
-  'GET_EXAMPLEDIRS))'#010+
+  '        $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGE',
+  'T_EXAMPLEDIRS))'#010+
   'endif'#010+
   #010+
   'fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_'+
@@ -2142,7 +2152,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'fpc_makefiles: fpc_makefile fpc_makefile_dirs'#010+
   #010+
   '[localmakefile]'#010+
-  '######','##############################################################'+
+  '#############','#######################################################'+
   '#'#010+
   '# Local Makefile'#010+
   '#####################################################################'#010+
@@ -2153,7 +2163,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   #010+
   '[userrules]'#010+
-  '###############','#####################################################'+
+  '######################','##############################################'+
   '#'#010+
   '# Users rules'#010+
   '#####################################################################'#010+
@@ -2161,7 +2171,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '[lclrules]'#010+
   '#####################################################################'#010+
   '# LCL Rules'#010+
-  '#######','#############################################################'+
+  '##############','######################################################'+
   '#'#010+
   #010+
   '# LCL Platform'#010+
@@ -2174,7 +2184,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   'export LCL_PLATFORM'#010+
   #010+
-  '# Check if the spec','ified LCLDIR is correct'#010+
+  '# Check if the specified L','CLDIR is correct'#010+
   'ifdef LCLDIR'#010+
   'override LCLDIR:=$(subst \,/,$(LCLDIR))'#010+
   'ifeq ($(wildcard $(LCLDIR)/units/$(LCL_PLATFORM)),)'#010+
@@ -2185,7 +2195,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   '# Check if the default LCLDIR is correct'#010+
-  'ifdef DE','FAULT_LCLDIR'#010+
+  'ifdef DEFAULT_L','CLDIR'#010+
   'override LCLDIR:=$(subst \,/,$(DEFAULT_LCLDIR))'#010+
   'ifeq ($(wildcard $(LCLDIR)/units/$(LCL_PLATFORM)),)'#010+
   'override LCLDIR=wrong'#010+
@@ -2194,7 +2204,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '# Check for development version'#010+
   'ifeq ($(LCLDIR),wrong)'#010+
-  'override LCLDIR=$(subst /units/$(LCL_','PLATFORM),,$(firstword $(wildca'+
+  'override LCLDIR=$(subst /units/$(LCL_PLATFOR','M),,$(firstword $(wildca'+
   'rd $(addsuffix /units/$(LCL_PLATFORM),$(BASEDIR)/lcl $(BASEDIR)))))'#010+
   'ifeq ($(LCLDIR),)'#010+
   'override LCLDIR=wrong'#010+
@@ -2203,7 +2213,7 @@ const fpcmakeini : array[0..215,1..240] of char=(
   #010+
   '# Check for release version'#010+
   'ifeq ($(LCLDIR),wrong)'#010+
-  'override LCLDIR=$(subst /units/$(LCL_','PLATFORM),,$(firstword $(wildca'+
+  'override LCLDIR=$(subst /units/$(LCL_PLATFOR','M),,$(firstword $(wildca'+
   'rd $(addsuffix /lib/lazarus/units/$(LCL_PLATFORM),/usr/local /usr))))'#010+
   'ifeq ($(LCLDIR),)'#010+
   'override LCLDIR=wrong'#010+
@@ -2211,15 +2221,15 @@ const fpcmakeini : array[0..215,1..240] of char=(
   'endif'#010+
   #010+
   '# Generate dirs'#010+
-  'override LCLUNITDIR:=$(wildcard $(LCLDIR)/units/$(LCL_PLATFORM) $(LCLD',
-  'IR)/units)'#010+
+  'override LCLUNITDIR:=$(wildcard $(LCLDIR)/units/$(LCL_PLATFORM) $(LCLD'+
+  'IR)/uni','ts)'#010+
   'override LCLCOMPONENTDIR:=$(wildcard $(LCLDIR)/.. $(LCLDIR)/../compone'+
   'nts $(LCLDIR)/components)'#010+
   'export LCLDIR LCLUNITDIR LCLCOMPONENTDIR'#010+
   #010+
   '# Add LCL dirs to paths'#010+
   'override REQUIRE_PACKAGESDIR+=$(LCLCOMPONENTDIR)'#010+
-  'override COMPILER_','UNITDIR+=$(LCLUNITDIR)'#010+
+  'override COMPILER_UNITDIR','+=$(LCLUNITDIR)'#010+
   #010+
   '[lclinforules]'#010+
   '#####################################################################'#010+
@@ -2227,14 +2237,14 @@ const fpcmakeini : array[0..215,1..240] of char=(
   '#####################################################################'#010+
   'override INFORULES+=lclinfo'#010+
   #010+
-  '.PHONY: lclinfo',#010+
+  '.PHONY: lclinfo'#010+
   #010+
-  'lclinfo:'#010+
+  'lclin','fo:'#010+
   '        @$(ECHO)  == LCL info =='#010+
   '        @$(ECHO)'#010+
   '        @$(ECHO)  Platform............. $(LCL_PLATFORM)'#010+
   '        @$(ECHO)  LCLDIR............... $(LCLDIR)'#010+
   '        @$(ECHO)  LCL Unit dir......... $(LCLUNITDIR)'#010+
-  '        @$(ECHO)  L','CL Component dir.... $(LCLCOMPONENTDIR)'#010+
+  '        @$(ECHO)  LCL Comp','onent dir.... $(LCLCOMPONENTDIR)'#010+
   '        @$(ECHO)'#010
 );

+ 9 - 1
utils/fpcm/fpcmake.ini

@@ -1152,13 +1152,21 @@ endif
 ifndef CROSSBOOTSTRAP
 ifneq ($(BINUTILSPREFIX),)
 override FPCOPT+=-XP$(BINUTILSPREFIX)
-override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
 endif
 ifneq ($(BINUTILSPREFIX),)
 override FPCOPT+=-Xr$(RLINKPATH)
 endif
 endif
 
+# When BINUTILSPREFIX is given and we are not cross-compiling then use
+# it while compiling the fpmake file. (For example to build i386-freebsd
+# with BINUTILSPREFIX=i386-)
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+endif
+endif
+
 # User dirs should be first, so they are looked at first
 ifdef UNITDIR
 override FPCOPT+=$(addprefix -Fu,$(UNITDIR))

+ 166 - 128
utils/fpdoc/Makefile

@@ -1,8 +1,8 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2011/12/30]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/26]
 #
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
@@ -420,9 +420,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
 endif
@@ -478,382 +484,394 @@ ifeq ($(FULL_TARGET),mipsel-linux)
 override TARGET_PROGRAMS+=fpdoc makeskel unitdiff fpclasschart
 endif
 ifeq ($(FULL_TARGET),i386-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf
+override CLEAN_UNITS+=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
 endif
 ifeq ($(FULL_TARGET),i386-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+override CLEAN_FILES+=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 endif
 override INSTALL_FPCPACKAGE=y
 ifeq ($(FULL_TARGET),i386-linux)
@@ -988,9 +1006,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override COMPILER_OPTIONS+=-S2h
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 override COMPILER_OPTIONS+=-S2h
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override COMPILER_OPTIONS+=-S2h
 endif
@@ -1994,6 +2018,13 @@ REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-PASSRC=1
 REQUIRE_PACKAGES_CHM=1
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-PASSRC=1
+REQUIRE_PACKAGES_CHM=1
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
@@ -2001,6 +2032,13 @@ REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-PASSRC=1
 REQUIRE_PACKAGES_CHM=1
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-PASSRC=1
+REQUIRE_PACKAGES_CHM=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_UNIVINT=1

+ 3 - 3
utils/fpdoc/Makefile.fpc

@@ -12,7 +12,7 @@ packages_darwin=univint
 
 [target]
 programs=fpdoc makeskel unitdiff fpclasschart
-rst=dwriter fpdoc dglobals makeskel dwlinear
+rst=dwriter fpdoc dglobals makeskel dwlinear 
 # removed to reduce dependencies of rpm.
 #dirs_linux_i386=fpde
 #dirs_win32=fpde
@@ -27,8 +27,8 @@ fpcpackage=y
 fpcdir=../..
 
 [clean]
-units=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf 
-files=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst
+units=dglobals dwriter dw_xml sh_pas dw_html dw_latex dw_ipf dw_txt dw_man dwlinear dw_linrtf dw_dxml fpdocproj fpdocxmlopts mkfpdoc
+files=dwriter.rst fpdoc.rst dglobals.rst makeskel.rst fpdocopts.rst
 
 [rules]
 .NOTPARALLEL:

+ 55 - 34
utils/fpdoc/dglobals.pp

@@ -145,11 +145,20 @@ resourcestring
   SUsageOption130  = '--output=name     use name as the output name.';
   SUsageOption140  = '                  Each backend interpretes this as needed.';
   SUsageOption150  = '--package=name    Set the package name for which to create output';
+  SUsageOption155  = '--project=file    Use file as project file';  
   SUsageOption160  = '--show-private    Show private methods.';
   SUsageOption170  = '--warn-no-node    Warn if no documentation node was found.';
   SUsageOption180  = '--mo-dir=dir      Set directory where language files reside to dir';
   SUsageOption190  = '--parse-impl      (Experimental) try to parse implementation too';
   SUsageOption200 =  '--dont-trim	Don''t trim XML contents';
+  SUsageOption210 =  '--write-project=file Do not write documentation, create project file instead';
+  SUsageOption220 =  '--verbose         Write more information on the screen';
+  SUsageOption230 =  '--dry-run         Only parse sources and XML, do not create output';
+  SUsageOption240 =  '--descr-dir=Dir   Add All XML files in Dir to list of description files';
+  SUsageOption250 =  '--input-dir=Dir   Add All *.pp and *.pas files in Dir to list of input files';
+  SUsageOption260 =  '--write-project=file Write all command-line options to a project file';
+  
+
   SUsageFormats        = 'The following output formats are supported by this fpdoc:';
   SUsageBackendHelp    = 'Specify an output format, combined with --help to get more help for this backend.';
   SUsageFormatSpecific = 'Output format "%s" supports the following options:';
@@ -173,7 +182,7 @@ type
 
   // Assumes a list of TObject instances and frees them on destruction
 
-  TObjectList = class(TList)
+  TObjectList = class(TFPList)
   public
     destructor Destroy; override;
   end;
@@ -261,19 +270,24 @@ type
 
 
   // The main FPDoc engine
+  TFPDocLogLevel = (dleWarnNoNode);
+  TFPDocLogLevels = set of TFPDocLogLevel;
 
   { TFPDocEngine }
-
   TFPDocEngine = class(TPasTreeContainer)
   private
+    FDocLogLevels: TFPDocLogLevels;
   protected
     DescrDocs: TObjectList;             // List of XML documents
     DescrDocNames: TStringList;         // Names of the XML documents
     FRootLinkNode: TLinkNode;
     FRootDocNode: TDocNode;
-    FPackages: TList;                   // List of TFPPackage objects
+    FPackages: TFPList;                   // List of TFPPackage objects
     CurModule: TPasModule;
     CurPackageDocNode: TDocNode;
+    Function LogEvent(E : TFPDocLogLevel) : Boolean;
+    Procedure DoLog(Const Msg : String);overload;
+    Procedure DoLog(Const Fmt : String; Args : Array of const);overload;
   public
     Output: String;
     HasContentFile: Boolean;
@@ -313,7 +327,7 @@ type
 
     property RootLinkNode: TLinkNode read FRootLinkNode;
     property RootDocNode: TDocNode read FRootDocNode;
-    property Package: TPasPackage read FPackage;
+    Property DocLogLevels : TFPDocLogLevels Read FDocLogLevels Write FDocLogLevels;
   end;
 
 
@@ -325,6 +339,7 @@ Function IsExampleNode(Example : TDomNode) : Boolean;
 // returns true is link is an absolute URI
 Function IsLinkAbsolute(ALink: String): boolean;
 
+
 implementation
 
 uses SysUtils, Gettext, XMLRead;
@@ -430,7 +445,7 @@ begin
     { No child found, let's create one if we are at the end of the path }
     if DotPos > 0 then
       // !!!: better throw an exception
-      WriteLn('Link path does not exist: ', APathName);
+      Raise Exception.CreateFmt('Link path does not exist: %s',[APathName]);
     Result := TLinkNode.Create(ChildName, ALinkTo);
     if Assigned(LastChild) then
       LastChild.FNextSibling := Result
@@ -545,6 +560,22 @@ end;
 
 { TFPDocEngine }
 
+function TFPDocEngine.LogEvent(E: TFPDocLogLevel): Boolean;
+begin
+  Result:=E in FDocLogLevels;
+end;
+
+procedure TFPDocEngine.DoLog(const Msg: String);
+begin
+  If Assigned(OnLog) then
+    OnLog(Self,Msg);
+end;
+
+procedure TFPDocEngine.DoLog(const Fmt: String; Args: array of const);
+begin
+  DoLog(Format(Fmt,Args));
+end;
+
 constructor TFPDocEngine.Create;
 begin
   inherited Create;
@@ -554,7 +585,7 @@ begin
   FRootDocNode := TDocNode.Create('', nil);
   HidePrivate := True;
   InterfaceOnly:=True;
-  FPackages := TList.Create;
+  FPackages := TFPList.Create;
 end;
 
 destructor TFPDocEngine.Destroy;
@@ -696,7 +727,7 @@ var
      result:=Copy(AName, DotPos2 + 1, length(AName)-dotpos2);
   end;
 
-  function SearchInList(clslist:TList;s:string):TPasElement;
+  function SearchInList(clslist:TFPList;s:string):TPasElement;
   var i : integer;
       ClassEl: TPasElement;
   begin
@@ -793,7 +824,7 @@ var
        end
      else
        if cls<>result then
-         writeln('Warning : ancestor class ',clname,' of class ',cls.name,' could not be resolved');
+         DoLog('Warning : ancestor class %s of class %s could not be resolved',[clname,cls.name]);
 end;
 
 function CreateAliasType (alname,clname : string;parentclass:TPasClassType; out cl2 :TPasClassType):TPasAliasType;
@@ -853,7 +884,7 @@ end;
                  begin
                    // writeln('Found alias pair ',clname,' = ',alname);   
                    if not assigned(CreateAliasType(alname,clname,cls,cls2)) then
-                      writeln('Warning: creating alias ',alname,' for ',clname,' failed!');
+                      DoLog('Warning: creating alias %s for %s failed!',[alname,clname]);
                  end 
                else
                  cls2:=ResolveAndLinkClass(clname,j=0,cls);
@@ -1084,7 +1115,7 @@ function TFPDocEngine.FindElement(const AName: String): TPasElement;
   function FindInModule(AModule: TPasModule; const LocalName: String): TPasElement;
   
   var
-    l: TList;
+    l: TFPList;
     i: Integer;
     
   begin
@@ -1104,30 +1135,20 @@ function TFPDocEngine.FindElement(const AName: String): TPasElement;
 
 var
   i: Integer;
-  //ModuleName, LocalName: String;
   Module: TPasElement;
 begin
-{!!!: Don't know if we ever will have to use the following:
-  i := Pos('.', AName);
-  if i <> 0 then
-  begin
-    WriteLn('Dot found in name: ', AName);
-    Result := nil;
-  end else
-  begin}
-    Result := FindInModule(CurModule, AName);
-    if not Assigned(Result) then
-      for i := CurModule.InterfaceSection.UsesList.Count - 1 downto 0 do
+  Result := FindInModule(CurModule, AName);
+  if not Assigned(Result) then
+    for i := CurModule.InterfaceSection.UsesList.Count - 1 downto 0 do
+    begin
+      Module := TPasElement(CurModule.InterfaceSection.UsesList[i]);
+      if Module.ClassType = TPasModule then
       begin
-        Module := TPasElement(CurModule.InterfaceSection.UsesList[i]);
-        if Module.ClassType = TPasModule then
-        begin
-          Result := FindInModule(TPasModule(Module), AName);
-          if Assigned(Result) then
-            exit;
-        end;
+        Result := FindInModule(TPasModule(Module), AName);
+        if Assigned(Result) then
+          exit;
       end;
-  {end;}
+    end;
 end;
 
 function TFPDocEngine.FindModule(const AName: String): TPasModule;
@@ -1181,7 +1202,7 @@ function TFPDocEngine.ResolveLink(AModule: TPasModule;
 var
   i: Integer;
   ThisPackage: TLinkNode;
-  UnitList: TList;
+  UnitList: TFPList;
 
   function CanWeExit(AResult: string): boolean;
   var
@@ -1192,7 +1213,7 @@ var
   end;
 
 begin
-  system.WriteLn('ResolveLink(', AModule.Name, ' - ', ALinkDest, ')... ');
+  // system.WriteLn('ResolveLink(', AModule.Name, ' - ', ALinkDest, ')... ');
   if Length(ALinkDest) = 0 then
   begin
     SetLength(Result, 0);
@@ -1414,7 +1435,7 @@ begin
        WarnNoNode and
        (Length(AElement.PathName)>0) and
        (AElement.PathName[1]='#') then
-      Writeln('No documentation node found for identifier : ',AElement.PathName);
+      DoLog(Format('No documentation node found for identifier : %s',[AElement.PathName]));
     end;
 end;
 
@@ -1422,7 +1443,7 @@ function TFPDocEngine.FindDocNode(ARefModule: TPasModule;
   const AName: String): TDocNode;
 var
   CurPackage: TDocNode;
-  UnitList: TList;
+  UnitList: TFPList;
   i: Integer;
 begin
   if Length(AName) = 0 then

+ 1 - 1
utils/fpdoc/dw_dxml.pp

@@ -465,7 +465,7 @@ procedure TDocumentation.DoVisit(obj: TPasResString);
 begin
   WriteLn(f, ' ': lvl * 2, '<resourceString name="' + obj.Name + '">');
   WriteLn(f, ' ': lvl * 2 + 2, '<value>');
-  WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.Value));
+  WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.GetDeclaration(false)));
   WriteLn(f, ' ': lvl * 2 + 2, '</value>');
   WriteLn(f, ' ': lvl * 2, '</resourceString>');
 end;

+ 71 - 30
utils/fpdoc/dw_html.pp

@@ -503,7 +503,7 @@ constructor THTMLWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
   end;
 
   procedure AddPages(AElement: TPasElement; ASubpageIndex: Integer;
-    AList: TList);
+    AList: TFPList);
   var
     i: Integer;
   begin
@@ -739,7 +739,7 @@ begin
           WriteHTMLFile(PageDoc, Filename);
         except
 	  on E: Exception do
-            WriteLn(Format(SErrCouldNotCreateFile, [FileName, e.Message]));
+            DoLog(SErrCouldNotCreateFile, [FileName, e.Message]);
         end;
       finally
         PageDoc.Free;
@@ -750,7 +750,7 @@ begin
   begin
     if not FileExists(FCSSFile) Then
       begin
-        Writeln(stderr,'Can''t find CSS file "',FCSSFILE,'"');
+        DoLog('Can''t find CSS file "%s"',[FCSSFILE]);
         halt(1);
       end;
     TempStream := TMemoryStream.Create;
@@ -1096,8 +1096,12 @@ begin
   s := ResolveLinkID(a);
   if Length(s) = 0 then
   begin
-
-    WriteLn(Format(SErrUnknownLinkID, [a]));
+    if assigned(module) then
+      s:=module.name
+    else
+      s:='?';
+    if a='' then a:='<empty>';
+    DoLog(SErrUnknownLinkID, [s,a]);
     PushOutputNode(CreateEl(CurOutputNode, 'b'));
   end else
     PushOutputNode(CreateLink(CurOutputNode, s));
@@ -1507,7 +1511,7 @@ function THTMLWriter.AppendHyperlink(Parent: TDOMNode;
   Element: TPasElement): TDOMElement;
 var
   s: String;
-  UnitList: TList;
+  UnitList: TFPList;
   i: Integer;
   ThisPackage: TLinkNode;
 begin
@@ -2046,7 +2050,12 @@ begin
        s:= ResolveLinkID(l);
        if Length(s)=0 then
          begin
-         WriteLn(Format(SErrUnknownLinkID, [l]));
+         if assigned(module) then
+           s:=module.name
+         else
+           s:='?';
+         if l='' then l:='<empty>';
+         DoLog(SErrUnknownLinkID, [s,l]);
          NewEl := CreateEl(ParaEl,'b')
          end
        else
@@ -2346,7 +2355,7 @@ end;
 
 procedure THTMLWriter.AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
 
-  Procedure AddElementsFromList(L : TStrings; List : TList);
+  Procedure AddElementsFromList(L : TStrings; List : TFPList);
   
   Var
     I : Integer;
@@ -2539,12 +2548,12 @@ procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
       end;
   end;
 
-  procedure CreateSimpleSubpage(const ATitle: DOMString; AList: TList);
+  procedure CreateSimpleSubpage(const ATitle: DOMString; AList: TFPList);
   var
     TableEl, TREl, TDEl, CodeEl: TDOMElement;
     i, j: Integer;
     Decl: TPasElement;
-    SortedList: TList;
+    SortedList: TFPList;
     DocNode: TDocNode;
     S : String;
 
@@ -2552,7 +2561,7 @@ procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
     AppendMenuBar(ASubpageIndex);
     S:=ATitle;
     AppendTitle(Format(SDocUnitTitle + ': %s', [AModule.Name, S]));
-    SortedList := TList.Create;
+    SortedList := TFPList.Create;
     try
       for i := 0 to AList.Count - 1 do
       begin
@@ -2598,7 +2607,7 @@ procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
       ParaEl := CreatePara(BodyElement);
       AppendText(CreateCode(ParaEl), Decl.Name);
       CreateEl(ParaEl, 'br');
-      AppendText(ParaEl, Decl.Value);
+      AppendText(ParaEl, Decl.Expr.getDeclaration(true));
     end;
   end;
   
@@ -2709,8 +2718,8 @@ begin
         AppendShortDescrCell(TREl, EnumValue);
         AppendNbSp(CodeEl, 2);
         s := EnumValue.Name;
-        if EnumValue.IsValueUsed then
-          s := s + ' = ' + IntToStr(EnumValue.Value);
+        if EnumValue.AssignedValue<>'' then
+          s := s + ' = ' + EnumValue.AssignedValue;
         if i < TPasEnumType(AType).Values.Count - 1 then
           s := s + ',';
         AppendPasSHFragment(CodeEl, s, 0);
@@ -2754,8 +2763,8 @@ begin
           AppendShortDescrCell(TREl, EnumValue);
           AppendNbSp(CodeEl, 2);
           s := EnumValue.Name;
-          if EnumValue.IsValueUsed then
-            s := s + ' = ' + IntToStr(EnumValue.Value);
+          if (EnumValue.AssignedValue<>'') then
+            s := s + ' = ' + EnumValue.AssignedValue;
           if i < EnumType.Values.Count - 1 then
             s := s + ',';
           AppendPasSHFragment(CodeEl, s, 0);
@@ -2828,6 +2837,22 @@ var
     AppendText(ParaEl, '] ');
   end;
 
+  procedure AppendGenericTypes(CodeEl : TDomElement; AList : TFPList; isSpecialize : Boolean);
+
+  Var
+    I : integer;
+  begin
+    for I:=0 to AList.Count-1 do
+      begin
+      if I=0 then
+        AppendSym(CodeEl, '<')
+      else
+        AppendSym(CodeEl, ',');
+      AppendText(CodeEl,TPasGenericTemplateType(AList[i]).Name);
+      end;
+    AppendSym(CodeEl, '>');
+  end;
+
   procedure CreateMainPage;
   var
     TableEl, TREl, TDEl, CodeEl: TDOMElement;
@@ -2858,24 +2883,39 @@ var
     TDEl := CreateTD(TREl);
     CodeEl := CreateCode(CreatePara(TDEl));
     AppendKw(CodeEl, 'type');
+    if AClass.ObjKind=okGeneric then
+      AppendKw(CodeEl, ' generic ');
     AppendText(CodeEl, ' ' + AClass.Name + ' ');
+    if AClass.ObjKind=okGeneric then
+      AppendGenericTypes(CodeEl,AClass.GenericTemplateTypes,false);
     AppendSym(CodeEl, '=');
     AppendText(CodeEl, ' ');
-    AppendKw(CodeEl, ObjKindNames[AClass.ObjKind]);
+    if AClass.ObjKind<>okSpecialize then
+      AppendKw(CodeEl, ObjKindNames[AClass.ObjKind])
+    else
+      AppendKw(CodeEl, ' specialize ');
 
     if Assigned(AClass.AncestorType) then
     begin
-      AppendSym(CodeEl, '(');
-      AppendHyperlink(CodeEl, AClass.AncestorType);
-      if AClass.Interfaces.count>0 Then
+      if AClass.ObjKind=okSpecialize then
+        begin
+        AppendHyperlink(CodeEl, AClass.AncestorType);
+        AppendGenericTypes(CodeEl,AClass.GenericTemplateTypes,true)
+        end
+      else
         begin
-          for i:=0 to AClass.interfaces.count-1 do
-           begin
-             AppendSym(CodeEl, ', ');
-             AppendHyperlink(CodeEl,TPasClassType(AClass.Interfaces[i]));
-           end; 
+        AppendSym(CodeEl, '(');
+        AppendHyperlink(CodeEl, AClass.AncestorType);
+        if AClass.Interfaces.count>0 Then
+          begin
+            for i:=0 to AClass.interfaces.count-1 do
+             begin
+               AppendSym(CodeEl, ', ');
+               AppendHyperlink(CodeEl,TPasClassType(AClass.Interfaces[i]));
+             end;
+          end;
+        AppendSym(CodeEl, ')');
         end;
-      AppendSym(CodeEl, ')');
     end;
 
     if AClass.Members.Count > 0 then
@@ -2965,7 +3005,8 @@ var
     end;
 
     AppendText(CodeEl, ' '); // !!!: Dirty trick, necessary for current XML writer
-    AppendKw(CodeEl, 'end');
+    if not AClass.IsShortDefinition then
+      AppendKw(CodeEl, 'end');
     AppendSym(CodeEl, ';');
 
 
@@ -3093,13 +3134,13 @@ var
 
   procedure CreateSortedSubpage(AFilter: TMemberFilter);
   var
-    List: TList;
+    List: TFPList;
     ThisClass: TPasClassType;
     i, j: Integer;
     Member: TPasElement;
     TableEl, TREl, TDEl, ParaEl, LinkEl: TDOMElement;
   begin
-    List := TList.Create;
+    List := TFPList.Create;
     try
       ThisClass := AClass;
       while True do
@@ -3393,7 +3434,7 @@ end;
 
 procedure THTMLWriter.WriteDoc;
 begin
-   WriteLn(Format(SWritingPages, [PageCount]));
+   DoLog(SWritingPages, [PageCount]);
    WriteHTMLPages;
 end;
 

+ 3 - 3
utils/fpdoc/dw_man.pp

@@ -91,7 +91,7 @@ Type
     procedure WriteManRef(APasElement : TPasElement; Comma : Boolean);
     procedure WriteModuleSeealso(Comma : Boolean);
 
-    procedure SortElementList(List : TList);
+    procedure SortElementList(List : TFPList);
     Function  GetDescrString(AContext: TPasElement; DescrNode: TDOMElement) : String;
     function  ConstValue(ConstDecl: TPasConst): String; virtual;
     procedure WriteCommentLine;
@@ -192,7 +192,7 @@ constructor TManWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
     Engine.AddLink(AElement.PathName, ElementToManPage(AElement));
   end;
 
-  procedure AddList(AElement: TPasElement; AList: TList);
+  procedure AddList(AElement: TPasElement; AList: TFPList);
   var
     i: Integer;
   begin
@@ -1722,7 +1722,7 @@ begin
   Result:=CompareText(TPasElement(P1).Name,TPasElement(P2).Name);
 end;
 
-procedure TManWriter.SortElementList(List : TList);
+procedure TManWriter.SortElementList(List : TFPList);
 
 begin
   List.Sort(@CompareElements);

+ 9 - 7
utils/fpdoc/dwlinear.pp

@@ -34,7 +34,7 @@ Type
     // Auxiliary routines
     procedure DescrBeginURL(const AURL: DOMString); override; // Provides a default implementation
     procedure DescrEndURL; override;
-    procedure SortElementList(List : TList);
+    procedure SortElementList(List : TFPList);
     procedure StartListing(Frames: Boolean);
     Function  ShowMember(M : TPasElement) : boolean;
     procedure StartChapter(ChapterName : String; ChapterLabel : String); virtual;
@@ -877,10 +877,12 @@ begin
       WriteLabel(TypeDecl);
       WriteIndex(TypeDecl);
       If TypeDecl is TPasEnumType then
-        begin
-        WriteENumElements(TypeDecl as TPasEnumType);
-        end;
-      WriteDescr(TypeDecl);
+        WriteENumElements(TypeDecl as TPasEnumType)
+      else If (TypeDecl is TPasSetType)
+              and (TPasSetType(TypeDecl).EnumType is TPasEnumType)
+              and (TPasSetType(TypeDecl).EnumType.Name='') then
+        WriteENumElements(TPasSetType(TypeDecl).EnumType as TPasEnumType);
+      WriteDescr(TypeDecl,DocNode);
       If Assigned(DocNode) and Assigned(DocNode.Version) then
         begin
         Writeln(Format('%s : ',[SDocVersion]));
@@ -1152,7 +1154,7 @@ begin
   Result:=CompareText(TPasElement(P1).Name,TPasElement(P2).Name);
 end;
 
-procedure TLinearWriter.SortElementList(List : TList);
+procedure TLinearWriter.SortElementList(List : TFPList);
 
 begin
   List.Sort(@CompareElements);
@@ -1227,7 +1229,7 @@ constructor TLinearWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
     Engine.AddLink(AElement.PathName, GetLabel(AElement));
   end;
 
-  procedure AddList(AElement: TPasElement; AList: TList);
+  procedure AddList(AElement: TPasElement; AList: TFPList);
   var
     i: Integer;
   begin

+ 19 - 4
utils/fpdoc/dwriter.pp

@@ -45,7 +45,7 @@ resourcestring
 
   SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
   SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
-  SErrUnknownLinkID = 'Warning: Target ID of <link> is unknown: "%s"';
+  SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s" is unknown: "%s"';
   SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
   SErrUnknownLink = 'Could not resolve link to "%s"';
   SErralreadyRegistered = 'Class for output format "%s" already registered';
@@ -63,6 +63,8 @@ type
     Destructor Destroy; override;
   end;
 
+  TWriterLogEvent = Procedure(Sender : TObject; Const Msg : String) of object;
+
   { TFPDocWriter }
 
   TFPDocWriter = class
@@ -74,6 +76,8 @@ type
     procedure ConvertURL(AContext: TPasElement; El: TDOMElement);
     
   protected
+    Procedure DoLog(Const Msg : String);
+    Procedure DoLog(Const Fmt : String; Args : Array of const);
     procedure Warning(AContext: TPasElement; const AMsg: String);
     procedure Warning(AContext: TPasElement; const AMsg: String;
       const Args: array of const);
@@ -370,7 +374,7 @@ end;
 Procedure TFPDocWriter.DescrWriteImageEl(const AFileName, ACaption,ALinkName : DOMString); 
 
 begin
-  system.writeln(ClassName,': No support for images yet: ',AFileName,' (caption: "',ACaption,'")');
+  DoLog('%s : No support for images yet: %s (caption: "%s")',[ClassName,AFileName,ACaption]);
 end;
 
 { ---------------------------------------------------------------------
@@ -388,9 +392,9 @@ end;
 procedure TFPDocWriter.Warning(AContext: TPasElement; const AMsg: String);
 begin
   if (AContext<>nil) then
-    WriteLn('[', AContext.PathName, '] ', AMsg)
+    DoLog('[%s] %s',[AContext.PathName,AMsg])
   else
-    WriteLn('[<no context>] ', AMsg);
+    DoLog('[<no context>] %s', [AMsg]);
 end;
 
 procedure TFPDocWriter.Warning(AContext: TPasElement; const AMsg: String;
@@ -612,6 +616,17 @@ begin
   DescrEndURL;
 end;
 
+procedure TFPDocWriter.DoLog(const Msg: String);
+begin
+  If Assigned(FEngine.OnLog) then
+    FEngine.OnLog(Self,Msg);
+end;
+
+procedure TFPDocWriter.DoLog(const Fmt: String; Args: array of const);
+begin
+  DoLog(Format(Fmt,Args));
+end;
+
 function TFPDocWriter.ConvertExtShort(AContext: TPasElement;
   Node: TDOMNode): Boolean;
 begin

+ 1 - 1
utils/fpdoc/fpclasschart.pp

@@ -35,7 +35,7 @@ resourcestring
 
 Const
   RootNames : Array[TPasObjKind] of string
-            = ('Objects', 'Classes', 'Interfaces');
+            = ('Objects', 'Classes', 'Interfaces','Generics','Specializations');
 
 type
 

+ 12 - 8
utils/fpdoc/fpdoc.lpi

@@ -13,7 +13,6 @@
       <Title Value="FPDoc Documentation generator"/>
       <ResourceType Value="res"/>
       <UseXPManifest Value="True"/>
-      <Icon Value="0"/>
     </General>
     <i18n>
       <EnableI18N LFM="False"/>
@@ -41,7 +40,7 @@
         <PackageName Value="FCL"/>
       </Item1>
     </RequiredPackages>
-    <Units Count="14">
+    <Units Count="15">
       <Unit0>
         <Filename Value="fpdoc.pp"/>
         <IsPartOfProject Value="True"/>
@@ -60,7 +59,7 @@
       <Unit3>
         <Filename Value="dw_html.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="dw_html"/>
+        <UnitName Value="dw_HTML"/>
       </Unit3>
       <Unit4>
         <Filename Value="dw_ipflin.pas"/>
@@ -70,7 +69,7 @@
       <Unit5>
         <Filename Value="dw_latex.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="dw_latex"/>
+        <UnitName Value="dw_LaTeX"/>
       </Unit5>
       <Unit6>
         <Filename Value="dwlinear.pp"/>
@@ -80,7 +79,7 @@
       <Unit7>
         <Filename Value="dw_linrtf.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="dw_linrtf"/>
+        <UnitName Value="dw_LinRTF"/>
       </Unit7>
       <Unit8>
         <Filename Value="dw_man.pp"/>
@@ -90,7 +89,7 @@
       <Unit9>
         <Filename Value="dwriter.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="dwriter"/>
+        <UnitName Value="dWriter"/>
       </Unit9>
       <Unit10>
         <Filename Value="dw_txt.pp"/>
@@ -100,7 +99,7 @@
       <Unit11>
         <Filename Value="dw_xml.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="dw_xml"/>
+        <UnitName Value="dw_XML"/>
       </Unit11>
       <Unit12>
         <Filename Value="fpdocproj.pas"/>
@@ -112,10 +111,15 @@
         <IsPartOfProject Value="True"/>
         <UnitName Value="fpdocxmlopts"/>
       </Unit13>
+      <Unit14>
+        <Filename Value="mkfpdoc.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="mkfpdoc"/>
+      </Unit14>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
-    <Version Value="9"/>
+    <Version Value="11"/>
     <Target>
       <Filename Value="fpdoc"/>
     </Target>

+ 88 - 110
utils/fpdoc/fpdoc.pp

@@ -16,7 +16,7 @@
 program FPDoc;
 
 uses
-  SysUtils, Classes, Gettext, DOM, XMLWrite, PasTree, PParser, custapp,
+  SysUtils, Classes, Gettext, custapp,
   dGlobals,  // GLobal definitions, constants.
   dwriter,   // TFPDocWriter definition.
   dwlinear,  // Linear (abstract) writer
@@ -27,13 +27,8 @@ uses
   dw_ipflin, // IPF writer (new linear output)
   dw_man,    // Man page writer
   dw_linrtf, // linear RTF writer
-  dw_txt, fpdocproj, fpdocxmlopts;    // TXT writer
+  dw_txt, fpdocproj, mkfpdoc;    // TXT writer
 
-const
-  DefOSTarget    = {$I %FPCTARGETOS%};
-  DefCPUTarget   = {$I %FPCTARGETCPU%};
-  DefFPCVersion  = {$I %FPCVERSION%};
-  DefFPCDate     = {$I %FPCDATE%};
 
 Type
 
@@ -41,14 +36,16 @@ Type
 
   TFPDocAplication = Class(TCustomApplication)
   private
-    FProject : TFPDocProject;
-    FProjectFile : Boolean;
+    FCreator : TFPDocCreator;
     FPackage : TFPDocPackage;
+    FDryRun,
+    FProjectFile : Boolean;
+    FWriteProjectFile : String;
   Protected
+    procedure OutputLog(Sender: TObject; const Msg: String);
     procedure ParseCommandLine;
     procedure Parseoption(const S: String);
     Procedure Usage(AnExitCode : Byte);
-    procedure CreateDocumentation(APackage : TFPDocPackage; Options : TEngineOptions);
     Procedure DoRun; override;
   Public
     Constructor Create(AOwner : TComponent); override;
@@ -83,14 +80,21 @@ begin
   Writeln(SUsageOption130);
   Writeln(SUsageOption140);
   Writeln(SUsageOption150);
+  Writeln(SUsageOption155);
   Writeln(SUsageOption160);
   Writeln(SUsageOption170);
   Writeln(SUsageOption180);
   Writeln(SUsageOption190);
   Writeln(SUsageOption200);
+  Writeln(SUsageOption210);
+  Writeln(SUsageOption220);
+  Writeln(SUsageOption230);
+  Writeln(SUsageOption240);
+  Writeln(SUsageOption250);
+  Writeln(SUsageOption260);
   L:=TStringList.Create;
   Try
-    Backend:=FProject.OPtions.Backend;
+    Backend:=FCreator.OPtions.Backend;
     If (Backend='') then
       begin
       Writeln;
@@ -126,7 +130,7 @@ end;
 destructor TFPDocAplication.Destroy;
 
 begin
-  FreeAndNil(FProject);
+  FreeAndNil(FCreator);
   Inherited;
 end;
 
@@ -140,6 +144,10 @@ begin
     end;
 end;
 
+procedure TFPDocAplication.OutputLog(Sender: TObject; const Msg: String);
+begin
+  Writeln(StdErr,Msg);
+end;
 
 procedure TFPDocAplication.ParseCommandLine;
 
@@ -166,14 +174,14 @@ begin
     s:=ParamStr(I);
     If ProjectOpt(S) then
       ParseOption(s);
-    If (FProject.Packages.Count=1) then
-      FPackage:=FProject.Packages[0]
-    else if (FProject.Options.DefaultPackageName<>'') then
-      Fpackage:=FProject.Packages.FindPackage(FProject.Options.DefaultPackageName);
+    If (FCreator.Packages.Count=1) then
+      FPackage:=FCreator.Packages[0]
+    else if (FCreator.Options.DefaultPackageName<>'') then
+      Fpackage:=FCreator.Packages.FindPackage(FCreator.Options.DefaultPackageName);
     end;
-  If FProject.Packages.Count=0 then
+  If FCreator.Project.Packages.Count=0 then
     begin
-    FPackage:=FProject.Packages.Add as  TFPDocPackage;
+    FPackage:=FCreator.Packages.Add as  TFPDocPackage;
     end;
   // Check package
   for i := 1 to ParamCount do
@@ -188,15 +196,38 @@ begin
     If Not (ProjectOpt(s) or PackageOpt(S)) then
       ParseOption(s);
     end;
-  if (FPackage=Nil) or (FPackage.Name='') then
-    begin
-    Writeln(SNeedPackageName);
-    Usage(1);
-    end;
+  SelectedPackage; // Will print error if none available.
 end;
 
 procedure TFPDocAplication.Parseoption(Const S : String);
 
+  procedure AddDirToFileList(List: TStrings; const ADirName, AMask: String);
+
+  Var
+    Info : TSearchRec;
+    D : String;
+
+  begin
+    if (ADirName<>'') and not DirectoryExists(ADirName) then
+       OutputLog(Self,'Directory '+ADirName+' does not exist')
+    else
+      begin
+      if (ADirName='.') or (ADirName='') then
+        D:=''
+      else
+        D:=IncludeTrailingPathDelimiter(ADirName);
+      If (FindFirst(D+AMask,0,Info)=0) then
+        try
+          Repeat
+            If (Info.Attr and faDirectory)=0 then
+              List.Add(D+Info.name);
+          Until FindNext(Info)<>0;
+        finally
+          FindClose(Info);
+        end;
+      end;
+  end;
+
   procedure AddToFileList(List: TStrings; const FileName: String);
   var
     f: Text;
@@ -224,15 +255,15 @@ begin
   if (s = '-h') or (s = '--help') then
     Usage(0)
   else if s = '--hide-protected' then
-    FProject.Options.HideProtected := True
+    FCreator.Options.HideProtected := True
   else if s = '--warn-no-node' then
-    FProject.Options.WarnNoNode := True
+    FCreator.Options.WarnNoNode := True
   else if s = '--show-private' then
-    FProject.Options.ShowPrivate := False
+    FCreator.Options.ShowPrivate := False
   else if s = '--stop-on-parser-error' then
-    FProject.Options.StopOnParseError := True
+    FCreator.Options.StopOnParseError := True
   else if s = '--dont-trim' then
-    FProject.Options.donttrim := True
+    FCreator.Options.donttrim := True
   else
     begin
     i := Pos('=', s);
@@ -249,29 +280,35 @@ begin
     if (Cmd = '--project') or (Cmd='-p') then
       begin
       FProjectFile:=True;
-      With TXMLFPDocOptions.Create(self) do
-        try
-          LoadOptionsFromFile(FProject,Arg);
-        finally
-          Free;
-        end;
+      FCreator.LoadProjectFile(Arg);
       end
     else if (Cmd = '--descr') then
       AddToFileList(SelectedPackage.Descriptions, Arg)
+    else if (Cmd = '--descr-dir') then
+      AddDirToFileList(SelectedPackage.Descriptions, Arg, '*.xml')
     else if (Cmd = '-f') or (Cmd = '--format') then
       begin
       Arg:=UpperCase(Arg);
       If FindWriterClass(Arg)=-1 then
         WriteLn(StdErr, Format(SCmdLineInvalidFormat, [Arg]))
       else
-        FProject.Options.BackEnd:=Arg;
+        FCreator.Options.BackEnd:=Arg;
       end
     else if (Cmd = '-l') or (Cmd = '--lang') then
-      FProject.Options.Language := Arg
+      FCreator.Options.Language := Arg
     else if (Cmd = '-i') or (Cmd = '--input') then
       AddToFileList(SelectedPackage.Inputs, Arg)
+    else if (Cmd = '--input-dir') then
+      begin
+      AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pp');
+      AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pas');
+      end
     else if (Cmd = '-o') or (Cmd = '--output') then
       SelectedPackage.Output := Arg
+    else if (Cmd = '-v') or (Cmd = '--verbose') then
+      FCreator.Verbose:=true
+    else if (Cmd = '-n') or (Cmd = '--dry-run') then
+      FDryRun:=True
     else if Cmd = '--content' then
       SelectedPackage.ContentFile := Arg
     else if Cmd = '--import' then
@@ -279,88 +316,28 @@ begin
     else if Cmd = '--package' then
       begin
       If FProjectFile then
-        FPackage:=FProject.Packages.FindPackage(Arg)
+        FPackage:=FCreator.Packages.FindPackage(Arg)
       else
         FPackage.Name:=Arg;
       end
     else if Cmd = '--ostarget' then
-      FProject.Options.OSTarget := Arg
+      FCreator.Options.OSTarget := Arg
     else if Cmd = '--cputarget' then
-      FProject.Options.CPUTarget := Arg
+      FCreator.Options.CPUTarget := Arg
     else if Cmd = '--mo-dir' then
-      FProject.Options.modir := Arg
+      FCreator.Options.modir := Arg
     else if Cmd = '--parse-impl' then
-      FProject.Options.InterfaceOnly:=false
+      FCreator.Options.InterfaceOnly:=false
+    else if Cmd = '--write-project' then
+      FWriteProjectFile:=Arg
     else
       begin
-      FProject.Options.BackendOptions.Add(Cmd);
-      FProject.Options.BackendOptions.Add(Arg);
+      FCreator.Options.BackendOptions.Add(Cmd);
+      FCreator.Options.BackendOptions.Add(Arg);
       end;
     end;
 end;
 
-
-procedure TFPDocAplication.CreateDocumentation(APackage : TFPDocPackage; Options : TEngineOptions);
-
-var
-  i,j: Integer;
-  WriterClass : TFPDocWriterClass;
-  Writer : TFPDocWriter;
-  Engine : TFPDocEngine;
-  Cmd,Arg : String;
-
-begin
-  Engine:=TFPDocEngine.Create;
-  try
-    For J:=0 to Apackage.Imports.Count-1 do
-      begin
-      Arg:=Apackage.Imports[j];
-      i := Pos(',', Arg);
-      Engine.ReadContentFile(Copy(Arg,1,i-1),Copy(Arg,i+1,Length(Arg)));
-      end;
-    for i := 0 to APackage.Descriptions.Count - 1 do
-      Engine.AddDocFile(APackage.Descriptions[i],Options.donttrim);
-    Engine.SetPackageName(APackage.Name);
-    Engine.Output:=APackage.Output;
-    Engine.HideProtected:=Options.HideProtected;
-    Engine.HidePrivate:=Not Options.ShowPrivate;
-    if Length(Options.Language) > 0 then
-      TranslateDocStrings(Options.Language);
-    for i := 0 to Fpackage.Inputs.Count - 1 do
-      try
-        ParseSource(Engine, APackage.Inputs[i], Options.OSTarget, Options.CPUTarget);
-      except
-        on e: EParserError do
-          If Options.StopOnParseError then
-            Raise
-          else
-            WriteLn(StdErr, Format('%s(%d,%d): %s',
-                    [e.Filename, e.Row, e.Column, e.Message]));
-      end;
-    WriterClass:=GetWriterClass(Options.Backend);
-    Writer:=WriterClass.Create(Engine.Package,Engine);
-    With Writer do
-      Try
-        If Options.BackendOptions.Count>0 then
-          for I:=0 to ((Options.BackendOptions.Count-1) div 2) do
-            begin
-            Cmd:=Options.BackendOptions[I*2];
-            Arg:=Options.BackendOptions[I*2+1];
-            If not InterPretOption(Cmd,Arg) then
-              WriteLn(StdErr, Format(SCmdLineInvalidOption,[Cmd+'='+Arg]));
-            end;
-        WriteDoc;
-      Finally
-        Free;
-      end;
-    if Length(FPackage.ContentFile) > 0 then
-      Engine.WriteContentFile(FPackage.ContentFile);
-  finally
-    FreeAndNil(Engine);
-  end;
-end;
-
-
 Procedure TFPDocAplication.DoRun;
 
 begin
@@ -374,7 +351,10 @@ begin
   WriteLn(SCopyright);
   WriteLn;
   ParseCommandLine;
-  CreateDocumentation(FPackage,FProject.Options);
+  if (FWriteProjectFile<>'') then
+    FCreator.CreateProjectFile(FWriteProjectFile)
+  else
+    FCreator.CreateDocumentation(FPackage,FDryRun);
   WriteLn(SDone);
   Terminate;
 end;
@@ -383,10 +363,8 @@ constructor TFPDocAplication.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
   StopOnException:=true;
-  FProject:=TFPDOCproject.Create(Nil);
-  FProject.Options.StopOnParseError:=False;
-  FProject.Options.CPUTarget:=DefCPUTarget;
-  FProject.Options.OSTarget:=DefOSTarget;
+  FCreator:=TFPDocCreator.Create(Self);
+  FCreator.OnLog:=@OutputLog;
 end;
 
 begin

+ 239 - 28
utils/fpdoc/fpdocxmlopts.pas

@@ -5,36 +5,53 @@ unit fpdocxmlopts;
 interface
 
 uses
-  Classes, SysUtils, fpdocproj, dom;
+  Classes, SysUtils, fpdocproj, dom, fptemplate;
 
 Type
-
-  { TXMLFPocOptions }
-
   { TXMLFPDocOptions }
 
   TXMLFPDocOptions = Class(TComponent)
+  private
   Protected
     Procedure Error(Const Msg : String);
     Procedure Error(Const Fmt : String; Args : Array of Const);
     Procedure LoadPackage(APackage : TFPDocPackage; E : TDOMElement); virtual;
     Procedure LoadPackages(Packages : TFPDocPackages; E : TDOMElement);
     Procedure LoadEngineOptions(Options : TEngineOptions; E : TDOMElement); virtual;
+    Procedure SaveEngineOptions(Options : TEngineOptions; XML : TXMLDocument; AParent : TDOMElement); virtual;
+    procedure SaveDescription(const ADescription: String; XML: TXMLDocument;  AParent: TDOMElement); virtual;
+    procedure SaveImportFile(const AImportFile: String; XML: TXMLDocument; AParent: TDOMElement);virtual;
+    procedure SaveInputFile(const AInputFile: String; XML: TXMLDocument; AParent: TDOMElement);virtual;
+    Procedure SavePackage(APackage : TFPDocPackage; XML : TXMLDocument; AParent : TDOMElement); virtual;
   Public
     Procedure LoadOptionsFromFile(AProject : TFPDocProject; Const AFileName : String);
     Procedure LoadFromXML(AProject : TFPDocProject; XML : TXMLDocument); virtual;
+    Procedure SaveOptionsToFile(AProject : TFPDocProject; Const AFileName : String);
+    procedure SaveToXML(AProject : TFPDocProject; ADoc: TXMLDocument); virtual;
   end;
   EXMLFPdoc = Class(Exception);
 
+Function IndexOfString(S : String; List : Array of string) : Integer;
+
+Const
+  OptionCount = 11;
+  OptionNames : Array[0..OptionCount] of string
+         = ('hide-protected','warn-no-node','show-private',
+            'stop-on-parser-error', 'ostarget','cputarget',
+            'mo-dir','parse-impl','format', 'language',
+            'package','dont-trim');
+
 implementation
 
-Uses XMLRead;
+Uses XMLRead, XMLWrite;
 
 Resourcestring
   SErrInvalidRootNode = 'Invalid options root node: Got "%s", expected "docproject"';
   SErrNoPackagesNode = 'No "packages" node found in docproject';
   SErrNoInputFile = 'unit tag without file attribute found';
   SErrNoDescrFile = 'description tag without file attribute';
+  SErrNoImportFile = 'Import tag without file attribute';
+  SErrNoImportPrefix = 'Import tag without prefix attribute';
 
 { TXMLFPDocOptions }
 
@@ -47,6 +64,7 @@ begin
     Dec(Result);
 end;
 
+
 procedure TXMLFPDocOptions.Error(Const Msg: String);
 begin
   Raise EXMLFPDoc.Create(Msg);
@@ -77,19 +95,26 @@ procedure TXMLFPDocOptions.LoadPackage(APackage: TFPDocPackage; E: TDOMElement);
 
   Function LoadDescription(I : TDOMElement) : String;
 
+  begin
+    Result:=I['file'];
+    If (Result='') then
+      Error(SErrNoDescrFile);
+  end;
+
+  Function LoadImport(I : TDOMElement) : String;
+
   Var
     S : String;
-
   begin
     Result:=I['file'];
     If (Result='') then
-      Error(SErrNoDescrFile);
+      Error(SErrNoImportFile);
+    S:=I['prefix'];
+    If (S='') then
+      Error(SErrNoImportPrefix);
+    Result:=Result+','+S;
   end;
 
-Const
-  OpCount = 0;
-  OpNames : Array[0..OpCount] of string
-          = ('');
 Var
   N,S : TDOMNode;
   O : TDomElement;
@@ -97,7 +122,7 @@ Var
 begin
   APackage.Name:=E['name'];
   APackage.output:=E['output'];
-  APackage.ContentFile:=E['contentfile'];
+  APackage.ContentFile:=E['content'];
   N:=E.FirstChild;
   While (N<>Nil) do
     begin
@@ -124,6 +149,16 @@ begin
           S:=S.NextSibling;
           end;
         end
+      else If (O.NodeName='imports') then
+        begin
+        S:=O.FirstChild;
+        While (S<>Nil) do
+          begin
+          If (S.NodeType=Element_Node) and (S.NodeName='import') then
+            APackage.Imports.add(LoadImport(S as TDomElement));
+          S:=S.NextSibling;
+          end;
+        end
       end;
     N:=N.NextSibling;
     end;
@@ -155,13 +190,6 @@ procedure TXMLFPDocOptions.LoadEngineOptions(Options: TEngineOptions;
     Result:=(v='true') or (v='1') or (v='yes');
   end;
 
-Const
-  NCount = 11;
-  ONames : Array[0..NCount] of string
-         = ('hide-protected','warn-no-node','show-private',
-            'stop-on-parser-error', 'ostarget','cputarget',
-            'mo-dir','parse-impl','format', 'language',
-            'package','dont-trim');
 
 Var
   O : TDOMnode;
@@ -175,7 +203,7 @@ begin
       begin
       N:=LowerCase(TDOMElement(o)['name']);
       V:=TDOMElement(o)['value'];
-      Case IndexOfString(N,ONames) of
+      Case IndexOfString(N,OptionNames) of
         0 : Options.HideProtected:=TrueValue(v);
         1 : Options.WarnNoNode:=TrueValue(v);
         2 : Options.ShowPrivate:=TrueValue(v);
@@ -197,19 +225,187 @@ begin
     end;
 end;
 
-procedure TXMLFPDocOptions.LoadOptionsFromFile(AProject: TFPDocProject;
-  const AFileName: String);
+procedure TXMLFPDocOptions.SaveToXML(AProject: TFPDocProject; ADoc: TXMLDocument);
+
+var
+  i: integer;
+  E,PE: TDOMElement;
+
+begin
+  E:=ADoc.CreateElement('docproject');
+  ADoc.AppendChild(E);
+  E:=ADoc.CreateElement('options');
+  ADoc.DocumentElement.AppendChild(E);
+  SaveEngineOptions(AProject.Options,ADoc,E);
+  E:=ADoc.CreateElement('packages');
+  ADoc.DocumentElement.AppendChild(E);
+  for i := 0 to AProject.Packages.Count - 1 do
+    begin
+    PE:=ADoc.CreateElement('package');
+    E.AppendChild(PE);
+    SavePackage(AProject.Packages[i],ADoc,PE);
+    end;
+end;
+
+Procedure TXMLFPDocOptions.SaveEngineOptions(Options : TEngineOptions; XML : TXMLDocument; AParent : TDOMElement);
+
+  procedure AddStr(const n, v: string);
+  var
+    E : TDOMElement;
+  begin
+    if (v='') then
+      Exit;
+    E:=XML.CreateElement('option');
+    AParent.AppendChild(E);
+    E['name'] := n;
+    E['value'] := v;
+  end;
+
+  procedure AddBool(const AName: string; B: Boolean);
+
+  begin
+    if B then
+      AddStr(Aname,'true')
+    else
+      AddStr(Aname,'false');
+  end;
+
+begin
+  AddStr('ostarget', Options.OSTarget);
+  AddStr('cputarget', Options.CPUTarget);
+  AddStr('mo-dir', Options.MoDir);
+  AddStr('format', Options.Backend);
+  AddStr('language', Options.Language);
+  AddStr('package', Options.DefaultPackageName);
+  AddBool('hide-protected', Options.HideProtected);
+  AddBool('warn-no-node', Options.WarnNoNode);
+  AddBool('show-private', Options.ShowPrivate);
+  AddBool('stop-on-parser-error', Options.StopOnParseError);
+  AddBool('parse-impl', Options.InterfaceOnly);
+  AddBool('dont-trim', Options.DontTrim);
+end;
+
+Procedure TXMLFPDocOptions.SaveInputFile(Const AInputFile : String; XML : TXMLDocument; AParent: TDOMElement);
+
+  Function GetNextWord(Var s : string) : String;
+
+  Const
+    WhiteSpace = [' ',#9,#10,#13];
+
+  var
+    i,j: integer;
+
+  begin
+    I:=1;
+    While (I<=Length(S)) and (S[i] in WhiteSpace) do
+      Inc(I);
+    J:=I;
+    While (J<=Length(S)) and (not (S[J] in WhiteSpace)) do
+      Inc(J);
+    if (I<=Length(S)) then
+      Result:=Copy(S,I,J-I);
+    Delete(S,1,J);
+  end;
+
+
+Var
+  S,W,F,O : String;
+
+begin
+  S:=AInputFile;
+  O:='';
+  F:='';
+  While (S<>'') do
+    begin
+    W:=GetNextWord(S);
+    If (W<>'') then
+      begin
+      if W[1]='-' then
+        begin
+        if (O<>'') then
+          O:=O+' ';
+        o:=O+W;
+        end
+      else
+        F:=W;
+      end;
+    end;
+  AParent['file']:=F;
+  AParent['options']:=O;
+end;
+
+Procedure TXMLFPDocOptions.SaveDescription(Const ADescription : String; XML : TXMLDocument; AParent: TDOMElement);
+
+begin
+  AParent['file']:=ADescription;
+end;
+
+procedure TXMLFPDocOptions.SaveImportFile(const AImportFile: String;
+  XML: TXMLDocument; AParent: TDOMElement);
+
+Var
+  I : integer;
+
+begin
+  I:=Pos(',',AImportFile);
+  AParent['file']:=Copy(AImportFile,1,I-1);
+  AParent['prefix']:=Copy(AImportFile,i+1,Length(AImportFile));
+end;
+
+Procedure TXMLFPDocOptions.SavePackage(APackage: TFPDocPackage; XML : TXMLDocument; AParent: TDOMElement);
+
+
+var
+  i: integer;
+  E,PE : TDomElement;
+
+begin
+  AParent['name']:=APackage.Name;
+  AParent['output']:=APackage.Output;
+  AParent['content']:=APackage.ContentFile;
+  // Units
+  PE:=XML.CreateElement('units');
+  AParent.AppendChild(PE);
+  for i:=0 to APackage.Inputs.Count-1 do
+    begin
+    E:=XML.CreateElement('unit');
+    PE.AppendChild(E);
+    SaveInputFile(APackage.Inputs[i],XML,E);
+    end;
+  // Descriptions
+  PE:=XML.CreateElement('descriptions');
+  AParent.AppendChild(PE);
+  for i:=0 to APackage.Descriptions.Count-1 do
+    begin
+    E:=XML.CreateElement('description');
+    PE.AppendChild(E);
+    SaveDescription(APackage.Descriptions[i],XML,E);
+    end;
+  // Imports
+  PE:=XML.CreateElement('imports');
+  AParent.AppendChild(PE);
+  for i:=0 to APackage.Imports.Count-1 do
+    begin
+    E:=XML.CreateElement('import');
+    PE.AppendChild(E);
+    SaveImportFile(APackage.Imports[i],XML,E);
+    end;
+end;
+
+
+
+procedure TXMLFPDocOptions.LoadOptionsFromFile(AProject: TFPDocProject; const AFileName: String);
 
 Var
   XML : TXMLDocument;
 
 begin
-   XMLRead.ReadXMLFile(XML,AFileName);
-   try
-     LoadFromXML(AProject,XML);
-   finally
-     FreeAndNil(XML);
-   end;
+  ReadXMLFile(XML,AFileName);
+  try
+    LoadFromXML(AProject,XML);
+  finally
+    FreeAndNil(XML);
+  end;
 end;
 
 procedure TXMLFPDocOptions.LoadFromXML(AProject: TFPDocProject;
@@ -232,5 +428,20 @@ begin
     LoadEngineOptions(AProject.Options,N as TDOMElement);
 end;
 
+Procedure TXMLFPDocOptions.SaveOptionsToFile(AProject: TFPDocProject; const AFileName: String);
+
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    SaveToXML(AProject,XML);
+    WriteXMLFile(XML, AFileName);
+  finally
+    XML.Free;
+  end;
+end;
+
 end.
 

+ 335 - 0
utils/fpdoc/mgrfpdocproj.pp

@@ -0,0 +1,335 @@
+unit mgrfpdocproj;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpdocproj, fpdocxmlopts;
+
+Type
+  { TFPDocProjectManager }
+
+  TFPDocProjectManager = Class(TComponent)
+  Private
+    FProject : TFPDocProject;
+    FPackage : TFPDocPackage;
+    FExpandMacros: Boolean;
+    FMacros: TStrings;
+    procedure SetMacros(AValue: TStrings);
+  protected
+    Procedure CheckPackage;
+    procedure GetItemsFromDirectory(AList: TStrings; ADirectory, AMask: String; ARecurse: Boolean);
+    procedure DoMacro(Sender: TObject; const TagString: String; TagParams: TStringList; out ReplaceText: String); virtual;
+    function ExpandMacrosInFile(AFileName: String): TStream; virtual;
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    Destructor Destroy; override;
+    procedure AddDescrFilesFromDirectory(Const ADirectory, AMask : String; ARecurse: Boolean);
+    procedure AddInputFilesFromDirectory(Const ADirectory, AMask, AOptions: String; ARecurse: Boolean);
+    procedure AddInputFile(Const AFile : String; AOptions : String = '');
+    procedure AddImportFile(Const AFile,APrefix : String);
+    procedure AddDescrFile(Const AFile : String);
+    procedure RemoveInputFile(Const AFile : String);
+    procedure RemoveDescrFile(Const AFile : String);
+    procedure WriteOptionFile(const AFileName: String);
+    procedure ReadOptionFile(const AFileName: String);
+    Procedure Selectpackage(Const APackageName : String);
+    Procedure AddPackage (Const APackageName : String);
+    procedure SetOption(Const AOption : String; Enable : Boolean = True);
+    Property Project : TFPDocProject Read FProject;
+    Property SelectedPackage : TFPDocPackage Read FPackage;
+    Property Macros : TStrings Read FMacros Write SetMacros;
+    Property ExpandMacros : Boolean Read FExpandMacros Write FExpandMacros;
+  end;
+  EMgrFPDoc = Class(Exception);
+
+implementation
+
+uses dom,xmlread,fptemplate;
+
+procedure TFPDocProjectManager.SetMacros(AValue: TStrings);
+begin
+  if FMacros=AValue then Exit;
+  FMacros.Assign(AValue);
+end;
+
+procedure TFPDocProjectManager.DoMacro(Sender: TObject; const TagString: String;
+  TagParams: TStringList; out ReplaceText: String);
+begin
+  ReplaceText:=FMacros.Values[TagString];
+end;
+
+
+Procedure TFPDocProjectManager.GetItemsFromDirectory(AList : TStrings; ADirectory,AMask : String; ARecurse : Boolean);
+
+Var
+  D : String;
+  Info : TSearchRec;
+
+begin
+  D:=ADirectory;
+  if (D='.') then
+    D:='';
+  if (D<>'') then
+    D:=includeTrailingPathDelimiter(D);
+  If FindFirst(D+AMask,0,info)=0 then
+    try
+      Repeat
+      if ((Info.Attr and faDirectory)=0) then
+        AList.add(D+Info.Name);
+      Until (FindNext(Info)<>0);
+    finally
+      FindClose(Info);
+    end;
+  If ARecurse and (FindFirst(ADirectory+AMask,0,info)=0) then
+    try
+      Repeat
+      if ((Info.Attr and faDirectory)<>0) then
+        GetItemsFromDirectory(Alist,IncludeTrailingPathDelimiter(D+Info.Name),AMask,ARecurse);
+      Until (FindNext(Info)<>0);
+    finally
+      FindClose(Info);
+    end;
+end;
+
+constructor TFPDocProjectManager.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FProject:=TFPDocProject.Create(Self);
+  FMacros:=TStringList.Create;
+end;
+
+destructor TFPDocProjectManager.Destroy;
+begin
+  FreeAndNil(FMacros);
+  FreeAndNil(FProject);
+  inherited Destroy;
+end;
+
+Function TFPDocProjectManager.ExpandMacrosInFile(AFileName : String) : TStream;
+
+Var
+  F : TFileStream;
+  T : TTemplateParser;
+
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    Result:=TMemoryStream.Create;
+    try
+      T:=TTemplateParser.Create;
+      try
+        T.StartDelimiter:='$(';
+        T.EndDelimiter:=')';
+        T.AllowTagParams:=true;
+        T.OnReplaceTag:=@DoMacro;
+        T.ParseStream(F,Result);
+      finally
+        T.Free;
+      end;
+      Result.Position:=0;
+    except
+      FreeAndNil(Result);
+      Raise;
+    end;
+  finally
+    F.Free;
+  end;
+end;
+
+Procedure TFPDocProjectManager.AddDescrFilesFromDirectory(const ADirectory,AMask : String; ARecurse : Boolean);
+
+Var
+  L : TStringList;
+  M : String;
+
+begin
+  CheckPackage;
+  M:=AMask;
+  if (M='') then
+    M:='*.xml';
+  L:=TStringList.Create;
+  try
+    GetItemsFromDirectory(L,ADirectory,M,ARecurse);
+    FPackage.Descriptions.AddStrings(L);
+  finally
+    L.Free;
+  end;
+end;
+
+Procedure TFPDocProjectManager.AddInputFilesFromDirectory(Const ADirectory,AMask,AOptions : String; ARecurse : Boolean);
+
+Var
+  L : TStringList;
+  I : integer;
+  M : String;
+
+begin
+  CheckPackage;
+  M:=AMask;
+  if (M='') then
+    M:='*.pp';
+  L:=TStringList.Create;
+  try
+    GetItemsFromDirectory(L,ADirectory,M,ARecurse);
+    For I:=0 to L.Count-1 do
+      AddInputFile(L[i],AOPtions);
+  finally
+    L.Free;
+  end;
+end;
+
+procedure TFPDocProjectManager.AddInputFile(const AFile: String; AOptions : String = '');
+
+Var
+  S : String;
+
+begin
+  CheckPackage;
+  S:=AFile;
+  If (AOptions<>'') then
+    S:=AOptions+' '+S;
+  FPackage.Inputs.Add(S);
+end;
+
+procedure TFPDocProjectManager.AddImportFile(const AFile, APrefix: String);
+
+begin
+  CheckPackage;
+  FPackage.Imports.Add(AFile+','+APrefix);
+end;
+
+procedure TFPDocProjectManager.AddDescrFile(const AFile: String);
+
+begin
+  CheckPackage;
+  if FPackage.Descriptions.IndexOf(AFile)<>-1 then
+    Raise EMgrFPDoc.Createfmt('Duplicate description file : "%s"',[AFile]);
+  FPackage.Descriptions.Add(AFile);
+end;
+
+procedure TFPDocProjectManager.RemoveInputFile(const AFile: String);
+
+Var
+  I : Integer;
+
+begin
+  I:=FPackage.Inputs.IndexOf(AFile);
+  If (I<>-1) then
+    FPackage.Inputs.Delete(I);
+end;
+
+procedure TFPDocProjectManager.RemoveDescrFile(const AFile: String);
+
+Var
+  I : Integer;
+
+begin
+  I:=FPackage.Descriptions.IndexOf(AFile);
+  If (I<>-1) then
+    FPackage.Descriptions.Delete(I);
+end;
+
+procedure TFPDocProjectManager.ReadOptionFile(Const AFileName : String);
+
+Var
+  XML : TXMLDocument;
+  S : TStream;
+
+begin
+  With TXMLFPDocOptions.Create(Self) do
+    try
+      if not (ExpandMacros) then
+        LoadOptionsFromFile(FProject,AFileName)
+      else
+        begin
+        S:=ExpandMacrosInFile(AFileName);
+        try
+          ReadXMLFile(XML,S,AFileName);
+          try
+            LoadFromXml(FProject,XML)
+          finally
+            XML.Free;
+          end;
+        finally
+          S.Free;
+        end;
+        end;
+    finally
+      Free;
+    end;
+end;
+
+procedure TFPDocProjectManager.Selectpackage(const APackageName: String);
+begin
+  FPackage:=FProject.Packages.FindPackage(APackageName);
+  If (FPackage=Nil) then
+    Raise EMgrFPDoc.CreateFmt('Unknown package : "%s"',[APackageName]);
+end;
+
+procedure TFPDocProjectManager.AddPackage(const APackageName: String);
+begin
+  if FProject.Packages.FindPackage(APackageName)<>Nil then
+    Raise EMgrFPDoc.CreateFmt('Duplicate package : "%s"',[APackageName]);
+  FPackage:=FProject.Packages.Add as TFPDocPackage;
+  FPackage.Name:=APackageName;
+end;
+
+procedure TFPDocProjectManager.SetOption(const AOption: String;
+  Enable: Boolean = true);
+
+Var
+  O,V : String;
+  P : Integer;
+  EO : TEngineOptions;
+
+begin
+  V:=LowerCase(AOption);
+  P:=Pos('=',V);
+  If (P=0) then
+    P:=Length(V)+1;
+  O:=Copy(V,1,P-1);
+  Delete(V,1,P);
+  EO:=FProject.Options;
+  Case IndexOfString(o,OptionNames) of
+    0 : EO.HideProtected:=Enable;
+    1 : EO.WarnNoNode:=Enable;
+    2 : EO.ShowPrivate:=Enable;
+    3 : EO.StopOnParseError:=Enable;
+    4 : EO.ostarget:=v;
+    5 : EO.cputarget:=v;
+    6 : EO.MoDir:=V;
+    7 : EO.InterfaceOnly:=Not Enable;
+    8 : EO.Backend:=V;
+    9 : EO.Language:=v;
+    10 : EO.DefaultPackageName:=V;
+    11 : EO.DontTrim:=Enable;
+  else
+    EO.BackendOptions.add('--'+O);
+    EO.BackendOptions.add(v);
+  end;
+end;
+
+procedure TFPDocProjectManager.WriteOptionFile(Const AFileName : String);
+
+begin
+  With TXMLFPDocOptions.Create(Self) do
+    try
+      SaveOptionsToFile(FProject,AFileName);
+    finally
+      Free;
+    end;
+end;
+
+procedure TFPDocProjectManager.CheckPackage;
+
+begin
+  if (FPackage=Nil) then
+    Raise EMgrFPDoc.Create('Error: No package selected');
+end;
+
+
+
+end.
+

+ 204 - 0
utils/fpdoc/mkfpdoc.pp

@@ -0,0 +1,204 @@
+unit mkfpdoc;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, dglobals, fpdocxmlopts, dwriter, pscanner, pparser, fpdocproj;
+
+const
+  DefOSTarget    = {$I %FPCTARGETOS%};
+  DefCPUTarget   = {$I %FPCTARGETCPU%};
+  DefFPCVersion  = {$I %FPCVERSION%};
+  DefFPCDate     = {$I %FPCDATE%};
+
+Type
+
+  { TFPDocCreator }
+
+  TFPDocCreator = Class(TComponent)
+  Private
+    FOnLog: TPasParserLogHandler;
+    FPParserLogEvents: TPParserLogEvents;
+    FProject : TFPDocProject;
+    FScannerLogEvents: TPScannerLogEvents;
+    FVerbose: Boolean;
+    function GetOptions: TEngineOptions;
+    function GetPackages: TFPDocPackages;
+  Protected
+    procedure SetVerbose(AValue: Boolean); virtual;
+    Procedure DoLog(Const Msg : String);
+    procedure DoLog(Const Fmt : String; Args : Array of Const);
+    procedure CreateOutput(APackage: TFPDocPackage; Engine: TFPDocEngine); virtual;
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    Destructor Destroy; override;
+    Procedure CreateDocumentation(APackage : TFPDocPackage; ParseOnly : Boolean); virtual;
+    Procedure CreateProjectFile(Const AFileName : string);
+    Procedure LoadProjectFile(Const AFileName: string);
+    Property Project : TFPDocProject Read FProject;
+    Property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
+    Property ParserLogEvents : TPParserLogEvents Read FPParserLogEvents Write FPParserLogEvents;
+    Property Verbose : Boolean Read FVerbose Write SetVerbose;
+    Property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
+    // Easy access
+    Property Options : TEngineOptions Read GetOptions;
+    Property Packages : TFPDocPackages Read GetPackages;
+
+  end;
+
+implementation
+
+{ TFPDocCreator }
+
+procedure TFPDocCreator.SetVerbose(AValue: Boolean);
+begin
+  if FVerbose=AValue then Exit;
+  FVerbose:=AValue;
+  if FVerbose then
+    begin
+    ScannerLogEvents:=[sleFile];
+    ParserLogEvents:=[];
+    end
+  else
+    begin
+    ScannerLogEvents:=[];
+    ParserLogEvents:=[];
+    end;
+end;
+
+procedure TFPDocCreator.DoLog(const Msg: String);
+begin
+  If Assigned(OnLog) then
+    OnLog(Self,Msg);
+end;
+
+procedure TFPDocCreator.DoLog(const Fmt: String; Args: array of const);
+begin
+  DoLog(Format(Fmt,Args));
+end;
+
+function TFPDocCreator.GetOptions: TEngineOptions;
+begin
+  Result:=FProject.Options;
+end;
+
+function TFPDocCreator.GetPackages: TFPDocPackages;
+begin
+  Result:=FProject.Packages;
+end;
+
+constructor TFPDocCreator.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FProject:=TFPDocProject.Create(Self);
+  FProject.Options.StopOnParseError:=False;
+  FProject.Options.CPUTarget:=DefCPUTarget;
+  FProject.Options.OSTarget:=DefOSTarget;
+end;
+
+destructor TFPDocCreator.Destroy;
+begin
+  FreeAndNil(FProject);
+  inherited Destroy;
+end;
+
+procedure TFPDocCreator.CreateOutput(APackage: TFPDocPackage;Engine : TFPDocEngine);
+
+Var
+  WriterClass : TFPDocWriterClass;
+  Writer : TFPDocWriter;
+  I : Integer;
+  Cmd,Arg : String;
+
+begin
+  WriterClass:=GetWriterClass(Options.Backend);
+  Writer:=WriterClass.Create(Engine.Package,Engine);
+  With Writer do
+    Try
+      If FVerbose then
+        DoLog('Writing documentation');
+      OnLog:=Self.OnLog;
+      If Options.BackendOptions.Count>0 then
+        for I:=0 to ((Options.BackendOptions.Count-1) div 2) do
+          begin
+          Cmd:=Options.BackendOptions[I*2];
+          Arg:=Options.BackendOptions[I*2+1];
+          If not InterPretOption(Cmd,Arg) then
+            DoLog(SCmdLineInvalidOption,[Cmd+'='+Arg]);
+          end;
+      WriteDoc;
+    Finally
+      Free;
+    end;
+  if Length(APackage.ContentFile) > 0 then
+    Engine.WriteContentFile(APackage.ContentFile);
+end;
+
+procedure TFPDocCreator.CreateDocumentation(APackage: TFPDocPackage; ParseOnly : Boolean);
+
+var
+  i,j: Integer;
+  Engine : TFPDocEngine;
+  Cmd,Arg : String;
+
+begin
+  Engine:=TFPDocEngine.Create;
+  try
+    For J:=0 to Apackage.Imports.Count-1 do
+      begin
+      Arg:=Apackage.Imports[j];
+      i := Pos(',', Arg);
+      Engine.ReadContentFile(Copy(Arg,1,i-1),Copy(Arg,i+1,Length(Arg)));
+      end;
+    for i := 0 to APackage.Descriptions.Count - 1 do
+      Engine.AddDocFile(APackage.Descriptions[i],Options.donttrim);
+    Engine.SetPackageName(APackage.Name);
+    Engine.Output:=APackage.Output;
+    Engine.OnLog:=Self.OnLog;
+    Engine.ScannerLogEvents:=Self.ScannerLogEvents;
+    Engine.ParserLogEvents:=Self.ParserLogEvents;
+    Engine.HideProtected:=Options.HideProtected;
+    Engine.HidePrivate:=Not Options.ShowPrivate;
+    if Length(Options.Language) > 0 then
+      TranslateDocStrings(Options.Language);
+    for i := 0 to APackage.Inputs.Count - 1 do
+      try
+        ParseSource(Engine, APackage.Inputs[i], Options.OSTarget, Options.CPUTarget);
+      except
+        on e: EParserError do
+          If Options.StopOnParseError then
+            Raise
+          else
+            DoLog('%s(%d,%d): %s',[e.Filename, e.Row, e.Column, e.Message]);
+      end;
+    if Not ParseOnly then
+      CreateOutput(APackage,Engine);
+  finally
+    FreeAndNil(Engine);
+  end;
+end;
+
+procedure TFPDocCreator.CreateProjectFile(Const AFileName: string);
+begin
+  With TXMLFPDocOptions.Create(Self) do
+  try
+    SaveOptionsToFile(FProject,AFileName);
+  finally
+    Free;
+  end;
+end;
+
+procedure TFPDocCreator.LoadProjectFile(const AFileName: string);
+begin
+  With TXMLFPDocOptions.Create(self) do
+    try
+      LoadOptionsFromFile(FProject,AFileName);
+    finally
+      Free;
+    end;
+end;
+
+end.
+

+ 70 - 0
utils/fpdoc/mkfpdocproj.lpi

@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="--input=test.xml --output=test.xml --package=test add-input-files -o me testunit3.pp"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="mkfpdocproj.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="mkfpdocproj"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="mgrfpdocproj.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="mgrfpdocproj"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+    </SearchPaths>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 428 - 0
utils/fpdoc/mkfpdocproj.pp

@@ -0,0 +1,428 @@
+program mkfpdocproj;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, SysUtils, CustApp, mgrfpdocproj;
+
+type
+
+  { TManageFPDocProjectApplication }
+
+  TManageFPDocProjectApplication = class(TCustomApplication)
+  private
+    FMGR : TFPDocProjectManager;
+    FPackageName,
+    FInputFileName,
+    FOutputFileName,
+    FCmd : String;
+    FCmdArgs,
+    FCmdOptions: TStrings;
+    procedure AddDescrFiles;
+    procedure AddDescriptionDirs;
+    procedure AddInputDirs;
+    procedure AddInputFiles;
+    procedure AddImportFiles;
+    function CmdNeedsPackage: Boolean;
+    procedure RemoveInputFiles;
+    procedure RemoveDescrFiles;
+    procedure AddPackages;
+    function CheckCmdOption(C: Char; S: String): Boolean;
+    function GetCmdOption(C: Char; S: String): String;
+    procedure SetOptions(Enable: Boolean);
+  protected
+    procedure ParseOptions;
+    Procedure Error(Const Msg : String);
+    procedure Usage(AExitCode: Integer);
+    procedure DoRun; override;
+  public
+    constructor Create(TheOwner: TComponent); override;
+    Destructor Destroy; override;
+  end;
+
+Resourcestring
+  SErrNeedArgument = 'Option at position %d needs an argument: %s';
+
+{ TManageFPDocProjectApplication }
+
+procedure TManageFPDocProjectApplication.Usage(AExitCode : Integer);
+
+Var
+  FN : String;
+  I : Integer;
+
+begin
+  FN:=ChangeFileExt(ExtractFileName(ParamStr(0)),'');
+  Writeln('Usage ',FN,' [options] command [command-options] command-args');
+  Writeln('Where options is one of ');
+  Writeln('  -i --input=file   Initialize project from named file.');
+  Writeln('  -o --output=file  Write project to named file. Default is input file.');
+  Writeln('  -p --package=name Package to perform operation on.');
+  Writeln('command is one of:');
+  Writeln('  add-packages');
+  Writeln('    Add arguments as package definitions to the file.');
+  Writeln('  add-description-dirs');
+  Writeln('    Scan directories for XML files to add as descriptions of selected package.');
+  Writeln('  add-input-dirs');
+  Writeln('    Scan directories for .pp or .pas files to add as inputs of selected package.');
+  Writeln('  add-input-files');
+  Writeln('    Add files as inputs of selected package.');
+  Writeln('  add-import-files');
+  Writeln('    Add files (format: "filename,prefix") to imports of selected package.');
+  Writeln('  add-descr-files');
+  Writeln('    Add files as description files of selected package.');
+  Writeln('  expand-macros');
+  Writeln('    read file and expand macros. Arguments specify macro values as Name=Value pairs');
+  Writeln('  remove-descr-files');
+  Writeln('    Remove files from description files of selected package.');
+  Writeln('  remove-input-files');
+  Writeln('    Remove files from input files of selected package.');
+  Writeln('  set-options');
+  Writeln('    Set named options (true) for project file.');
+  Writeln('    Valid option names : ');
+  Writeln('      hide-protected , warn-no-node, show-private, stop-on-parser-error,');
+  Writeln('      parse-impl, dont-trim');
+  Writeln('  unset-options');
+  Writeln('    UnSet named options (false) for project file.');
+  Halt(AExitCode);
+end;
+
+Function CheckOptionStr(O : String;Short : Char;Long : String): Boolean;
+begin
+  Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
+end;
+
+function TManageFPDocProjectApplication.CmdNeedsPackage : Boolean;
+
+begin
+ Result:=(FCMd<>'expand-macros') and (FCMD<>'set-options') and (FCmd<>'unset-options');
+end;
+
+procedure TManageFPDocProjectApplication.ParseOptions;
+
+  Function CheckOption(Index : Integer;Short : char;Long : String): Boolean;
+  begin
+    Result:=CheckOptionStr(ParamStr(Index),Short,Long);
+  end;
+
+  Function OptionArg(Var Index : Integer) : String;
+  Var
+    P : Integer;
+  begin
+    if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
+      begin
+        If Index<ParamCount then
+          begin
+            Inc(Index);
+            Result:=Paramstr(Index);
+          end
+        else
+          Error(Format(SErrNeedArgument,[Index,ParamStr(Index)]));
+      end
+    else If length(ParamStr(Index))>2 then
+      begin
+        P:=Pos('=',Paramstr(Index));
+        If (P=0) then
+          Error(Format(SErrNeedArgument,[Index,ParamStr(Index)]))
+        else
+          begin
+            Result:=Paramstr(Index);
+            Delete(Result,1,P);
+          end;
+      end;
+  end;
+
+Var
+  I : Integer;
+  S : String;
+
+begin
+  I:=0;
+  // We can't use the TCustomApplication option handling,
+  // because they cannot handle [general opts] [command] [cmd-opts] [args]
+  While (I<ParamCount) do
+    begin
+    Inc(I);
+    if (FCmd='') then
+      begin
+      if Checkoption(I,'i','input') then
+        FInputFileName:=OptionArg(i)
+      else if Checkoption(I,'o','output') then
+        FOutputFileName:=OptionArg(i)
+      else if CheckOption(I,'p','package') then
+        FPackageName:=OptionArg(i)
+      else if CheckOption(I,'h','help') then
+        Usage(0)
+      else if (ParamStr(i)<>'') then
+        begin
+        S:=ParamStr(i);
+        if (S[1]='-') then
+          Error('Unknown option : '+S)
+        else
+          FCmd:=lowercase(S)
+        end
+      end
+    else
+      begin
+      S:=ParamStr(I);
+      if (S<>'') then
+         if (S[1]<>'-') then
+           FCmdArgs.Add(S)
+         else
+           FCmdOptions.Add(S);
+      end;
+    end;
+  if (FOutputFileName='') then
+    FOutputFileName:=FInputFileName;
+  If (FOutputFileName='') then
+    Error('Need an output filename');
+  if (FPackageName='') and CmdNeedsPackage then
+    Error('Need a package name');
+  if (FCmd='') then
+    Error('Need a command');
+end;
+
+procedure TManageFPDocProjectApplication.Error(Const Msg: String);
+begin
+  Writeln('Error : ',Msg);
+  Usage(1);
+end;
+
+
+Function TManageFPDocProjectApplication.CheckCmdOption(C : Char; S : String) : Boolean;
+
+Var
+  I : integer;
+
+begin
+  I:=0;
+  Result:=False;
+  While (Not Result) and (I<FCmdOptions.Count) do
+    begin
+    Result:=CheckOptionStr(FCmdOptions[i],C,S);
+    Inc(I);
+    end;
+end;
+
+Function TManageFPDocProjectApplication.GetCmdOption(C : Char; S : String) : String;
+
+Var
+  I,P : integer;
+  B : Boolean;
+
+begin
+  I:=0;
+  B:=False;
+  While (Not B) and (I<FCmdOptions.Count) do
+    begin
+    B:=CheckOptionStr(FCmdOptions[i],C,S);
+    if B then
+      begin
+      Result:=FCmdOptions[I];
+      if (Length(Result)>1) and (Result[2]<>'-') then
+        begin
+        If I<FCmdOptions.Count-1 then
+          begin
+          Inc(I);
+          Result:=FCmdOptions[I];
+          end
+        else
+          Error(Format(SErrNeedArgument,[I,Result]));
+        end
+      else If length(Result)>2 then
+        begin
+        P:=Pos('=',Result);
+        If (P=0) then
+          Error(Format(SErrNeedArgument,[I,Result]))
+        else
+          Delete(Result,1,P);
+        end;
+      end;
+    Inc(I);
+    end;
+end;
+
+procedure TManageFPDocProjectApplication.AddDescriptionDirs;
+
+Var
+  Recursive: Boolean;
+  Mask : String;
+  I : Integer;
+begin
+  Recursive:=CheckCmdOption('r','recursive');
+  Mask:=GetCmdOption('m','mask');
+  if FCmdArgs.Count=0 then
+    FMGr.AddDescrFilesFromDirectory('',Mask,Recursive)
+  else
+    For I:=0 to FCmdArgs.Count-1 do
+      FMGr.AddDescrFilesFromDirectory(FCmdArgs[i],Mask,Recursive);
+end;
+
+procedure TManageFPDocProjectApplication.AddInputDirs;
+
+Var
+  Recursive: Boolean;
+  Options,Mask : String;
+  I : Integer;
+begin
+  Recursive:=CheckCmdOption('r','recursive');
+  Mask:=GetCmdOption('m','mask');
+  Options:=GetCmdOption('o','options');
+  if FCmdArgs.Count=0 then
+    FMGr.AddInputFilesFromDirectory('',Mask,Options,Recursive)
+  else
+    For I:=0 to FCmdArgs.Count-1 do
+      FMGr.AddInputFilesFromDirectory(FCmdArgs[i],Mask,Options,Recursive);
+end;
+
+procedure TManageFPDocProjectApplication.AddInputFiles;
+
+Var
+  Options : String;
+  I : Integer;
+
+begin
+  Options:=GetCmdOption('o','options');
+  For I:=0 to FCmdArgs.Count-1 do
+    FMGr.AddInputFile(FCmdArgs[i],Options);
+end;
+
+procedure TManageFPDocProjectApplication.AddImportFiles;
+
+Var
+  I,J : Integer;
+  F,P : String;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    begin
+    P:=FCmdArgs[i];
+    J:=Pos(',',P);
+    F:=Copy(P,1,J-1);
+    Delete(P,1,J);
+    FMGr.AddImportFile(F,P);
+    end;
+end;
+
+procedure TManageFPDocProjectApplication.RemoveInputFiles;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    FMGr.RemoveInputFile(FCmdArgs[i]);
+end;
+
+procedure TManageFPDocProjectApplication.RemoveDescrFiles;
+Var
+  I : Integer;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    FMGr.RemoveDescrFile(FCmdArgs[i]);
+end;
+
+procedure TManageFPDocProjectApplication.AddPackages;
+
+var
+  I : Integer;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    FMgr.AddPackage(FCmdArgs[i]);
+end;
+
+procedure TManageFPDocProjectApplication.AddDescrFiles;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    FMGr.AddDescrFile(FCmdArgs[i]);
+end;
+
+procedure TManageFPDocProjectApplication.SetOptions(Enable : Boolean);
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to FCmdArgs.Count-1 do
+    FMgr.SetOption(FCmdArgs[i],Enable);
+end;
+
+procedure TManageFPDocProjectApplication.DoRun;
+
+begin
+  ParseOptions;
+  if (FInputFileName='') then
+    FMGR.AddPackage(FPackageName)
+  else
+    begin
+    if (FCmd='expand-macros') then
+      begin
+      FMGR.Macros:=FCmdArgs;
+      FMGR.ExpandMacros:=true;
+      FMGR.ReadOptionFile(FInputFileName)
+      end
+    else
+      begin
+      FMGR.ReadOptionFile(FInputFileName);
+      if CmdNeedsPackage then
+        FMGR.SelectPackage(FPackageName);
+      end
+    end;
+  if (FCmd='add-packages') then
+    AddPackages
+  else if (FCmd='add-description-dirs') then
+    AddDescriptionDirs
+  else if (FCmd='add-input-dirs') then
+    AddInputDirs
+  else if (FCmd='add-input-files') then
+    AddInputFiles
+  else if (FCmd='add-import-files') then
+    AddImportFiles
+  else if (FCmd='add-description-files') then
+    AddDescrFiles
+  else if (FCmd='remove-input-files') then
+    RemoveInputFiles
+  else if (FCmd='remove-descr-files') then
+    RemoveDescrFiles
+  else if (FCmd='set-options') then
+    SetOptions(True)
+  else if (FCmd='unset-options') then
+    SetOptions(False)
+  else if (FCMd<>'expand-macros') then
+    Error(Format('Unknown command : "%s"',[FCmd]));
+  FMgr.WriteOptionFile(FOutputFileName);
+  Terminate;
+end;
+
+constructor TManageFPDocProjectApplication.Create(TheOwner: TComponent);
+begin
+  inherited Create(TheOwner);
+  StopOnException:=True;
+  FCmdArgs:=TStringList.Create;
+  FCmdOptions:=TStringList.Create;
+  FMGR:=TFPDocProjectManager.Create(Self);
+ end;
+
+destructor TManageFPDocProjectApplication.Destroy;
+begin
+  FreeAndNil(FMGR);
+  FreeAndNil(FCmdArgs);
+  FreeAndNil(FCmdOptions);
+  inherited Destroy;
+end;
+
+var
+  Application: TManageFPDocProjectApplication;
+begin
+  Application:=TManageFPDocProjectApplication.Create(nil);
+  Application.Title:='Program to manipulate FPDoc project files';
+  Application.Run;
+  Application.Free;
+end.
+

+ 1 - 1
utils/fpdoc/testunit.pp

@@ -40,7 +40,7 @@ Type
                             2 : (phi,Omega : Real);
                           end; 
                           
-//  TADeprecatedType = Integer deprecated;
+  TADeprecatedType = Integer deprecated;
                         
 Var
   ASimpleVar : Integer;  

+ 1 - 1
utils/fpdoc/unitdiff.pp

@@ -13,7 +13,7 @@
 }
 
 
-program MakeSkel;
+program unitdiff;
 
 uses
   SysUtils, Classes, Gettext,

Деякі файли не було показано, через те що забагато файлів було змінено