mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 21:18:01 +02:00
Tools: initial import of gir2pascal sources from https://github.com/n1tehawk/gir2pascal
This commit is contained in:
parent
455dc87b83
commit
697d41437c
4
tools/gir2pascal/.gitignore
vendored
Normal file
4
tools/gir2pascal/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.o
|
||||
*.or
|
||||
*.ppu
|
||||
*.rsj
|
336
tools/gir2pascal/LICENSE.md
Normal file
336
tools/gir2pascal/LICENSE.md
Normal file
@ -0,0 +1,336 @@
|
||||
GNU General Public License
|
||||
==========================
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
|
||||
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
### Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: **(1)** copyright the software, and
|
||||
**(2)** offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
**0.** This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The “Program”, below,
|
||||
refers to any such program or work, and a “work based on the Program”
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term “modification”.) Each licensee is addressed as “you”.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
**1.** You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
**2.** You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
* **a)** You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
* **b)** You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
* **c)** If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
**3.** You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
* **a)** Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
* **b)** Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
* **c)** Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
**4.** You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
**5.** You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
**6.** Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
**7.** If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
**8.** If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
**9.** The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and “any
|
||||
later version”, you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
**10.** If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
### NO WARRANTY
|
||||
|
||||
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
### How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the “copyright” line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w` and `show c` should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w` and `show c`; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a “copyright disclaimer” for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
9
tools/gir2pascal/Makefile
Normal file
9
tools/gir2pascal/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
SOURCES := $(wildcard *.pas)
|
||||
OPTIONS := -O2
|
||||
OBJ := *.o *.or *.ppu *.rsj
|
||||
|
||||
gir2pascal: gir2pascal.lpr $(SOURCES)
|
||||
fpc $(OPTIONS) $<
|
||||
|
||||
clean:
|
||||
rm -f gir2pascal $(OBJ)
|
52
tools/gir2pascal/README.md
Normal file
52
tools/gir2pascal/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
gir2pascal
|
||||
==========
|
||||
|
||||
This is my personal fork of the *gir2pascal* utility, a program to convert the
|
||||
GIR metadata format (= XML files) used by [GObject introspection][] into usable
|
||||
Pascal source code, suitable for generating corresponding language bindings.
|
||||
|
||||
The original is part of the Lazarus Code and Component Repository ([lazarus-ccr][],
|
||||
[wiki article][wiki-ccr]), see `applications/gobject-introspection/`.
|
||||
|
||||
I started working on this after I found a number of problems and shortcomings of
|
||||
the original *gir2pascal*, when trying to process the API description of [Poppler]
|
||||
version 0.82 (`Poppler-0.18.gir`), which also includes a number of dependencies
|
||||
(namely `GObject-2.0.gir`, `GLib-2.0.gir`, `Gio-2.0.gir` and `cairo-1.0.gir`).
|
||||
It's faily obvious that *gir2pascal* wasn't updated for quite some time, and it
|
||||
struggled with the current GIR format (e.g. not knowing about and thus showing
|
||||
numerous warnings for the `<source-position>` element). It also failed to handle
|
||||
the 'opaque' data types that an up-to-date `GLib-2.0.gir` seems to be using for
|
||||
its mutex locking.
|
||||
|
||||
Note:
|
||||
My changes were developed and tested using [fpc][] 3.0.4 and the default `*.gir`
|
||||
files that [Gentoo][] Linux installs for `poppler-0.82` and `glib-2.60.7`. The
|
||||
modified *gir2pascal* handles `Poppler-0.18.gir` and all its dependencies just
|
||||
fine, and the resulting `*.pas` files compile without errors. However, because
|
||||
I later decided to take a different approach (not using Poppler), I haven't
|
||||
checked if the generated API bindings are actually usable - so consider that
|
||||
part **untested**...
|
||||
|
||||
|
||||
---
|
||||
You can create a (set of) patch(es) from my branch, which should apply cleanly
|
||||
to the current (r6630) 'upstream' repository folder.
|
||||
|
||||
git format-patch master..nitehawk
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This project builds upon the original Lazarus CCR version and is thus intended
|
||||
to follow the same licensing principles. For the `gobject-introspection` folder
|
||||
this seems to be [GPL v2](LICENSE.md), as referenced in a number of file headers.
|
||||
|
||||
|
||||
[GObject introspection]: https://gi.readthedocs.io/
|
||||
[lazarus-ccr]: https://sourceforge.net/projects/lazarus-ccr/
|
||||
[wiki-ccr]: https://wiki.lazarus.freepascal.org/Lazarus-ccr_SourceForge_repository
|
||||
[poppler]: https://poppler.freedesktop.org/
|
||||
[fpc]: https://freepascal.org/
|
||||
[Gentoo]: https://gentoo.org/
|
443
tools/gir2pascal/commandlineoptions.pas
Normal file
443
tools/gir2pascal/commandlineoptions.pas
Normal file
@ -0,0 +1,443 @@
|
||||
unit CommandLineOptions;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Contnrs;
|
||||
|
||||
type
|
||||
|
||||
{ TOption }
|
||||
|
||||
TOption = class
|
||||
Names: array of String;
|
||||
Values: array of String;
|
||||
Identifier: Integer;
|
||||
HasArg: Boolean;
|
||||
Present: Boolean;
|
||||
Help: String;
|
||||
MultipleValues: Boolean;
|
||||
function LongestName: String;
|
||||
function Value: String;
|
||||
procedure AddValue(AValue: String);
|
||||
end;
|
||||
TCommandLineOptions = class;
|
||||
|
||||
|
||||
TOptionReadError = procedure(Sender: TObject; ErrorMessage: String) of object;
|
||||
|
||||
{ TCommandLineOptions }
|
||||
|
||||
TCommandLineOptions = class
|
||||
private
|
||||
FOnError: TOptionReadError;
|
||||
FOptions: TObjectList;
|
||||
FUnassignedArgs: TStringList;
|
||||
FStopReading: Boolean;
|
||||
function FindOptionByName(AName: String): TOption;
|
||||
function FindOptionByIdentifier(AIdentifier: Integer): TOption;
|
||||
procedure DoError(ErrorMessage: String); virtual;
|
||||
public
|
||||
// first setup options
|
||||
procedure SetOptions(ShortOptions: String; LongOptions: array of String);
|
||||
procedure AddOption(OptionNames: array of String; HasArg: Boolean = False; Help: String = ''; CanUseMultipleTimes: Boolean = False; Identifier: Integer = -1);
|
||||
// read from commandline
|
||||
procedure ReadOptions;
|
||||
|
||||
// string based
|
||||
function HasOption(AName: String): Boolean;
|
||||
function OptionValue(AName:String): String;
|
||||
function OptionValues(AName: String): TStrings;
|
||||
|
||||
// tag based
|
||||
function HasOption(AIdentifier: Integer): Boolean;
|
||||
function OptionValue(AIdentifier: Integer): String;
|
||||
function OptionValues(AIdentifier: Integer): TStrings;
|
||||
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function PrintHelp(MaxLineWidth: Integer): TStrings; virtual;
|
||||
property OnError: TOptionReadError read FOnError write FOnError;
|
||||
property OptionsMalformed: Boolean read FStopReading;
|
||||
end;
|
||||
resourcestring
|
||||
ErrUnknownOption = 'Option unknown: "%s"';
|
||||
ErrArgNeededNotPossible = 'Option "%s" requires an argument but an argument is not possible. (Hint: Use "%s" as last option in group "-%s" or use long option --%s)';
|
||||
ErrArgumentNeeded = 'Option "%s" requires an argument';
|
||||
ErrOptionHasNoArgument = 'Option "%s" does not accept arguments';
|
||||
ErrOnlyOneInstance = 'Option "%s" cannot be used more than once';
|
||||
ErrNoEqualsAllowed = 'Symbol "=" not allowed in argument group "-%s"';
|
||||
implementation
|
||||
|
||||
{ TOption }
|
||||
|
||||
function TOption.LongestName: String;
|
||||
var
|
||||
N: String;
|
||||
begin
|
||||
Result := '';
|
||||
for N in Names do
|
||||
begin
|
||||
if Length(N) > Length(Result) then
|
||||
Result := N;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TOption.Value: String;
|
||||
begin
|
||||
if Length(Values) > 0 then
|
||||
Exit(Values[0])
|
||||
else
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
procedure TOption.AddValue(AValue: String);
|
||||
begin
|
||||
SetLength(Values, Length(Values)+1);
|
||||
Values[High(Values)] := AValue;
|
||||
end;
|
||||
|
||||
{ TCommandLineOptions }
|
||||
|
||||
function TCommandLineOptions.FindOptionByName(AName: String): TOption;
|
||||
var
|
||||
Opt: TOption;
|
||||
N: String;
|
||||
begin
|
||||
Result := Nil;
|
||||
for Pointer(Opt) in FOptions do
|
||||
begin
|
||||
for N in Opt.Names do
|
||||
if AName = N then
|
||||
Exit(Opt)
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.FindOptionByIdentifier(AIdentifier: Integer
|
||||
): TOption;
|
||||
begin
|
||||
Result := Nil;
|
||||
end;
|
||||
|
||||
procedure TCommandLineOptions.DoError(ErrorMessage: String);
|
||||
begin
|
||||
FStopReading:=True;
|
||||
if Assigned(FOnError) then
|
||||
FOnError(Self, ErrorMessage)
|
||||
else
|
||||
WriteLn(ErrorMessage);
|
||||
end;
|
||||
|
||||
procedure TCommandLineOptions.SetOptions(ShortOptions: String;
|
||||
LongOptions: array of String);
|
||||
var
|
||||
L: String;
|
||||
S: String;
|
||||
HasArg: Boolean;
|
||||
P,
|
||||
E: PChar;
|
||||
begin
|
||||
P:= PChar(ShortOptions);
|
||||
E := P + Length(ShortOptions);
|
||||
|
||||
for L in LongOptions do
|
||||
begin
|
||||
S := P[0];
|
||||
if P+1 < E then
|
||||
HasArg:=P[1] = ':';
|
||||
Inc(P, 1+Ord(HasArg));
|
||||
AddOption([S, L], HasArg);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCommandLineOptions.AddOption(OptionNames: array of String;
|
||||
HasArg: Boolean; Help: String; CanUseMultipleTimes: Boolean; Identifier: Integer);
|
||||
var
|
||||
Opt: TOption;
|
||||
C: Integer;
|
||||
begin
|
||||
Opt := TOption.Create;
|
||||
C := Length(OptionNames);
|
||||
SetLength(Opt.Names, C);
|
||||
for C := Low(OptionNames) to High(OptionNames) do
|
||||
Opt.Names[C] := OptionNames[C];
|
||||
Opt.HasArg:=HasArg;
|
||||
Opt.Identifier:=Identifier;
|
||||
Opt.MultipleValues:=CanUseMultipleTimes;
|
||||
Opt.Help:=Help;
|
||||
FOptions.Add(Opt);
|
||||
end;
|
||||
|
||||
procedure TCommandLineOptions.ReadOptions;
|
||||
var
|
||||
OptIndex: Integer;
|
||||
procedure ReadOption(S, G: String; OptionPossible: Boolean);
|
||||
var
|
||||
Opt: TOption;
|
||||
Arg: String;
|
||||
HasEq: Integer = 0;
|
||||
begin
|
||||
HasEq := Pos('=', S);
|
||||
if HasEq > 0 then
|
||||
begin
|
||||
Arg := Copy(S, HasEq+1, Length(S));
|
||||
S := Copy(S,1, HasEq-1);
|
||||
end;
|
||||
|
||||
Opt := FindOptionByName(S);
|
||||
if Opt = Nil then
|
||||
begin
|
||||
DoError(Format(ErrUnknownOption, [S]));
|
||||
Exit;
|
||||
end;
|
||||
if Opt.HasArg and not OptionPossible then
|
||||
begin
|
||||
DoError(Format(ErrArgNeededNotPossible, [S, S, G, Opt.LongestName]));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if Opt.HasArg then
|
||||
begin
|
||||
if (OptIndex = Paramcount) and (HasEq = 0) then
|
||||
begin
|
||||
DoError(Format(ErrArgumentNeeded, [S]));
|
||||
Exit;
|
||||
end;
|
||||
if Opt.Present and not Opt.MultipleValues then
|
||||
begin
|
||||
DoError(Format(ErrOnlyOneInstance, [S]));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Verify???
|
||||
|
||||
if HasEq = 0 then
|
||||
begin
|
||||
Arg := ParamStr(OptIndex+1);
|
||||
Inc(OptIndex);
|
||||
end;
|
||||
Opt.AddValue(Arg);
|
||||
end
|
||||
else if HasEq > 0 then
|
||||
begin
|
||||
DoError(Format(ErrOptionHasNoArgument, [S]));
|
||||
end;
|
||||
|
||||
Opt.Present:=True;
|
||||
end;
|
||||
|
||||
procedure ReadSingleOptions(S: String);
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
if S[1] = '-' then // its a long option with 2 dashes : --option
|
||||
ReadOption(Copy(S,2,Length(S)), '', True)
|
||||
else // short options put together : -abcdefg
|
||||
begin
|
||||
if Pos('=', S) > 0 then
|
||||
begin
|
||||
DoError(Format(ErrNoEqualsAllowed,[S]));
|
||||
Exit;
|
||||
end;
|
||||
for I := 1 to Length(S) do
|
||||
ReadOption(S[I], S, I = Length(S));
|
||||
end;
|
||||
end;
|
||||
var
|
||||
RawOpt: String;
|
||||
begin
|
||||
OptIndex:=0;
|
||||
while OptIndex < Paramcount do
|
||||
begin
|
||||
if FStopReading then
|
||||
Exit;
|
||||
Inc(OptIndex);
|
||||
RawOpt := ParamStr(OptIndex);
|
||||
if (RawOpt[1] = '-') and (RawOpt <> '-') then // '-' is treated as an unassigned arg.
|
||||
ReadSingleOptions(Copy(RawOpt,2,Length(RawOpt)))
|
||||
else
|
||||
FUnassignedArgs.Add(RawOpt);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.HasOption(AName: String): Boolean;
|
||||
var
|
||||
Opt: TOption;
|
||||
begin
|
||||
Result := True;
|
||||
Opt := FindOptionByName(AName);
|
||||
if (Opt = nil) or not(Opt.Present) then
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.OptionValue(AName: String): String;
|
||||
var
|
||||
Opt: TOption;
|
||||
begin
|
||||
Opt := FindOptionByName(AName);
|
||||
Result := Opt.Value;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.OptionValues(AName: String): TStrings;
|
||||
var
|
||||
Opt: TOption;
|
||||
S: String;
|
||||
begin
|
||||
Opt := FindOptionByName(AName);
|
||||
Result := TStringList.Create;
|
||||
if Opt = nil then
|
||||
Exit;
|
||||
for S in Opt.Values do
|
||||
Result.Add(S);
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.HasOption(AIdentifier: Integer): Boolean;
|
||||
var
|
||||
Opt: TOption;
|
||||
begin
|
||||
Result := False;
|
||||
Opt := FindOptionByIdentifier(AIdentifier);
|
||||
if Opt = nil then
|
||||
Exit;
|
||||
|
||||
Result := Opt.Present;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.OptionValue(AIdentifier: Integer): String;
|
||||
var
|
||||
Opt: TOption;
|
||||
begin
|
||||
Result := '';
|
||||
Opt := FindOptionByIdentifier(AIdentifier);
|
||||
if Opt = nil then
|
||||
Exit;
|
||||
|
||||
Result := Opt.Value;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.OptionValues(AIdentifier: Integer): TStrings;
|
||||
var
|
||||
Opt: TOption;
|
||||
Tmp: String;
|
||||
begin
|
||||
Result := TStringList.Create;
|
||||
Opt := FindOptionByIdentifier(AIdentifier);
|
||||
if Opt = nil then
|
||||
Exit;
|
||||
|
||||
for Tmp in Opt.Values do
|
||||
Result.Add(Tmp);
|
||||
end;
|
||||
|
||||
constructor TCommandLineOptions.Create;
|
||||
begin
|
||||
FOptions := TObjectList.create(True);
|
||||
FUnassignedArgs := TStringList.Create;
|
||||
end;
|
||||
|
||||
destructor TCommandLineOptions.Destroy;
|
||||
begin
|
||||
FOptions.Clear;
|
||||
FOptions.Free;
|
||||
FUnassignedArgs.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TCommandLineOptions.PrintHelp(MaxLineWidth: Integer): TStrings;
|
||||
var
|
||||
Padding: array [0..255] of char;
|
||||
function Space(Orig: String; LengthNeeded: Integer; Before: Boolean = False): String;
|
||||
begin
|
||||
if not Before then
|
||||
Result := Orig+Copy(Padding,0,LengthNeeded-Length(Orig))
|
||||
else
|
||||
Result := Copy(Padding,0,LengthNeeded-Length(Orig))+Orig;
|
||||
end;
|
||||
|
||||
var
|
||||
Opt: TOption;
|
||||
Tmp: String;
|
||||
Line: String;
|
||||
LinePart: String;
|
||||
I, J: Integer;
|
||||
S,L,D: TStringList; // short opt, long opt, description
|
||||
SL, LL: String; // short line, long line
|
||||
SLL, LLL: Integer; //short line length, long line length
|
||||
LineSize: Integer;
|
||||
Gap: Integer;
|
||||
begin
|
||||
FillChar(Padding, 256, ' ');
|
||||
S := TStringList.Create;
|
||||
L := TStringList.Create;
|
||||
D := TStringList.Create;
|
||||
Result := TStringList.Create;
|
||||
for I := 0 to FOptions.Count-1 do
|
||||
begin
|
||||
SL := '';
|
||||
LL := '';
|
||||
Line := '';
|
||||
Opt := TOption(FOptions.Items[I]);
|
||||
for Tmp in Opt.Names do
|
||||
if Length(Tmp) = 1 then
|
||||
SL := SL + ' -' + Tmp
|
||||
else
|
||||
LL := LL + ' --' + Tmp;
|
||||
|
||||
S.Add(SL);
|
||||
L.Add(LL);
|
||||
D.Add(Opt.Help);
|
||||
end;
|
||||
SLL := 0;
|
||||
LLL := 0;
|
||||
|
||||
for Tmp in S do
|
||||
if Length(Tmp) > SLL then
|
||||
SLL := Length(Tmp);
|
||||
|
||||
for Tmp in L do
|
||||
if Length(Tmp) > LLL then
|
||||
LLL := Length(Tmp);
|
||||
|
||||
|
||||
for I := 0 to S.Count-1 do
|
||||
begin
|
||||
LinePart := '';
|
||||
SL := Space(S[I], SLL);
|
||||
LL := Space(L[I], LLL);
|
||||
Line := SL + ' ' + LL + ' '+ D[I];
|
||||
if Length(Line) > MaxLineWidth then
|
||||
begin
|
||||
LineSize:=MaxLineWidth;
|
||||
Gap := 0;
|
||||
repeat
|
||||
J := LineSize;
|
||||
//if J > Length(Line) then J := Length(Line);
|
||||
while (J > 0){ and (Length(Line) > 0)} do
|
||||
begin
|
||||
if (Line[J] = ' ') or (J = 1) then
|
||||
begin
|
||||
LinePart := Copy(Line, 1, J);
|
||||
LinePart := Space(LinePart, Length(LinePart)+Gap, True);
|
||||
Delete(Line,1,J);
|
||||
Result.Add(LinePart);
|
||||
break;
|
||||
end;
|
||||
Dec(J);
|
||||
end;
|
||||
Gap := SLL+1+LLL+4;
|
||||
LineSize := MaxLineWidth-(Gap);
|
||||
until Length(Line) = 0;
|
||||
end
|
||||
else
|
||||
Result.Add(Line);
|
||||
end;
|
||||
S.Free;
|
||||
L.Free;
|
||||
D.Free;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
BIN
tools/gir2pascal/gir2pascal.ico
Normal file
BIN
tools/gir2pascal/gir2pascal.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
118
tools/gir2pascal/gir2pascal.lpi
Normal file
118
tools/gir2pascal/gir2pascal.lpi
Normal file
@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<MainUnitHasCreateFormStatements Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<Icon Value="0"/>
|
||||
</General>
|
||||
<i18n>
|
||||
<EnableI18N LFM="False"/>
|
||||
</i18n>
|
||||
<VersionInfo>
|
||||
<StringTable ProductVersion=""/>
|
||||
</VersionInfo>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<DestinationDirectory Value="/tmp/publishedproject/"/>
|
||||
<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="-wni /home/andrew/programming/lazarus-ccr.old/applications/gobject-introspection/girfiles-from-felix/Gtk-3.0.gir -o /tmp/gir-out"/>
|
||||
<LaunchingApplication Use="True" PathPlusParams="/usr/bin/gnome-terminal -t 'Lazarus Run Output' -e '$(LazarusDir)/tools/runwait.sh $(TargetCmdLine)'"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<Units Count="11">
|
||||
<Unit0>
|
||||
<Filename Value="gir2pascal.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="girpascalwriter.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="girnamespaces.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girNameSpaces"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="girctypesmapping.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girCTypesMapping"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="girtokens.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girTokens"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="girerrors.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girErrors"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<Filename Value="girfiles.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girFiles"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="girobjects.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girObjects"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="girpascalclasswriter.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="girPascalClassWriter"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="girpascalwritertypes.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<Filename Value="commandlineoptions.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="CommandLineOptions"/>
|
||||
</Unit10>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<Target>
|
||||
<Filename Value="gir2pascal"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="4">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Name Value="EStringListError"/>
|
||||
</Item4>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
387
tools/gir2pascal/gir2pascal.lpr
Normal file
387
tools/gir2pascal/gir2pascal.lpr
Normal file
@ -0,0 +1,387 @@
|
||||
{
|
||||
gir2pascal.lpr
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
program gir2pascal;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{ $DEFINE CreatePascalClasses}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Classes, SysUtils,CommandLineOptions, DOM, XMLRead, girNameSpaces, girFiles,
|
||||
girpascalwriter, girErrors, girCTypesMapping, girTokens, girObjects,
|
||||
girPascalClassWriter, girpascalwritertypes{$IFDEF UNIX}, baseunix, termio{$ENDIF};
|
||||
|
||||
|
||||
type
|
||||
|
||||
{ TGirConsoleConverter }
|
||||
|
||||
TGirConsoleConverter = class
|
||||
private
|
||||
FCmdOptions: TCommandLineOptions;
|
||||
FWriteCount: Integer;
|
||||
FPaths: TStringList;
|
||||
FOutPutDirectory : String;
|
||||
FFileToConvert: String;
|
||||
FUnitPrefix: String;
|
||||
FOverWriteFiles: Boolean;
|
||||
FOptions: TgirOptions;
|
||||
procedure AddDefaultPaths;
|
||||
procedure AddPaths(APaths: String);
|
||||
procedure VerifyOptions;
|
||||
procedure Convert;
|
||||
|
||||
// options
|
||||
function CheckOptions: String;
|
||||
|
||||
//callbacks
|
||||
function NeedGirFile(AGirFile: TObject; NamespaceName: String) : TXMLDocument;
|
||||
// AName is the whole name unit.pas or file.c
|
||||
procedure WriteFile(Sender: TObject; AName: String; AStream: TStringStream);
|
||||
procedure Terminate;
|
||||
protected
|
||||
procedure DoRun; //override;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure WriteHelp; virtual;
|
||||
procedure Run;
|
||||
end;
|
||||
|
||||
|
||||
{ TGirConsoleConverter }
|
||||
|
||||
procedure TGirConsoleConverter.AddDefaultPaths;
|
||||
begin
|
||||
FPaths.Add('/usr/share/gir-1.0/');
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.AddPaths(APaths: String);
|
||||
var
|
||||
Strs: TStringList;
|
||||
Str: String;
|
||||
begin
|
||||
Strs := TStringList.Create;
|
||||
Strs.Delimiter:=':';
|
||||
Strs.StrictDelimiter:=True;
|
||||
Strs.DelimitedText:=APaths;
|
||||
|
||||
// so we can add the delimiter
|
||||
for Str in Strs do
|
||||
FPaths.Add(IncludeTrailingPathDelimiter(Str));
|
||||
|
||||
Strs.Free;
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.VerifyOptions;
|
||||
begin
|
||||
if not DirectoryExists(FOutPutDirectory) then
|
||||
begin
|
||||
WriteLn(Format('Output directory "%s" does not exist!', [FOutPutDirectory]));
|
||||
Terminate;
|
||||
end;
|
||||
if FFileToConvert = '' then
|
||||
begin
|
||||
WriteLn('No input file specified! See -h for options.');
|
||||
Terminate;
|
||||
Halt;
|
||||
end;
|
||||
if FCmdOptions.HasOption('objects') and FCmdOptions.HasOption('classes') then
|
||||
begin
|
||||
WriteLn('Cannot use options ''--objects'' and ''--classes'' together!.');
|
||||
Terminate;
|
||||
Halt;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGirConsoleConverter.NeedGirFile(AGirFile: TObject; NamespaceName: String): TXMLDocument;
|
||||
var
|
||||
Sr: TSearchRec;
|
||||
Path: String;
|
||||
begin
|
||||
WriteLn('Looking for gir file: ', NamespaceName);
|
||||
Result := nil;
|
||||
for Path in FPaths do
|
||||
begin
|
||||
WriteLn('Looking in path: ', Path);
|
||||
if FindFirst(Path+NamespaceName+'.gir', faAnyFile, Sr) = 0 then
|
||||
begin
|
||||
ReadXMLFile(Result, Path+Sr.Name);
|
||||
Exit;
|
||||
end;
|
||||
FindClose(Sr);
|
||||
end;
|
||||
if Result = nil then
|
||||
WriteLn('Fatal: Unable to find gir file: ',NamespaceName);
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.WriteFile(Sender: TObject; AName: String; AStream: TStringStream);
|
||||
var
|
||||
SStream: TFileStream;
|
||||
OutFileName: String;
|
||||
begin
|
||||
Inc(FWriteCount);
|
||||
OutFileName:=FOutPutDirectory+LowerCase(AName);
|
||||
if not FileExists(OutFileName)
|
||||
or (FileExists(OutFileName) and FOverWriteFiles) then
|
||||
begin
|
||||
WriteLn(Format('Writing: %s', [OutFileName]));
|
||||
AStream.Position:=0;
|
||||
ForceDirectories(FOutPutDirectory);
|
||||
SStream := TFileStream.Create(OutFileName, fmCreate or fmOpenReadWrite);
|
||||
SStream.CopyFrom(AStream,AStream.Size);
|
||||
SStream.Free;
|
||||
AStream.Free;
|
||||
end
|
||||
else
|
||||
begin
|
||||
WriteLn(Format('File %s already exists! Stopping.', [OutFileName]));
|
||||
Terminate;
|
||||
Halt;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.Terminate;
|
||||
begin
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.Convert;
|
||||
var
|
||||
Doc: TXMLDocument;
|
||||
girFile: TgirFile;
|
||||
Writer: TgirPascalWriter;
|
||||
StartTime, EndTime:TDateTime;
|
||||
begin
|
||||
StartTime := Now;
|
||||
ReadXMLFile(Doc, FFileToConvert);
|
||||
|
||||
girFile := TgirFile.Create(Self, FCmdOptions);
|
||||
girFile.OnNeedGirFile:=@NeedGirFile;
|
||||
girFile.ParseXMLDocument(Doc);
|
||||
Doc.Free;
|
||||
|
||||
Writer := TgirPascalWriter.Create(girFile.NameSpaces, FOptions, FUnitPrefix);
|
||||
Writer.OnUnitWriteEvent:= @WriteFile;
|
||||
Writer.GenerateUnits;
|
||||
|
||||
Writer.Free;
|
||||
EndTime := Now;
|
||||
|
||||
EndTime := EndTime-StartTime;
|
||||
WriteLn(Format('Converted %d file(s) in %f seconds',[FWriteCount, DateTimeToTimeStamp(EndTime).Time / 1000]));
|
||||
end;
|
||||
|
||||
function TGirConsoleConverter.CheckOptions: String;
|
||||
begin
|
||||
Result := '';
|
||||
//FCmdOptions.SetOptions(ShortOpts, LongOpts);
|
||||
with FCmdOptions do
|
||||
begin
|
||||
AddOption(['h', 'help'], False ,'Show this help message.');
|
||||
AddOption(['i', 'input'], True ,'.gir filename to convert.');
|
||||
AddOption(['o', 'output-directory'], True ,'Directory to write the resulting .pas files to. If not specified then the current working directory is used.');
|
||||
AddOption(['D', 'dynamic'], False , 'Use unit dynlibs and link at runtime');
|
||||
{$IFDEF CreatePascalClasses}
|
||||
AddOption(['s', 'seperate-units'], False ,'Creates seperate units for each gir file: (xConsts, xTypes, xFunctions, [xClasses, xObjects].');
|
||||
|
||||
AddOption(['C', 'classes'], False ,'Create Pascal classes that envelope/wrap the GObjects. Also forces ''-s''');
|
||||
AddOption(['O', 'objects'], False ,'OPTION NOT IMPLEMENTED YET. See Note below. '+
|
||||
'Creates a seperate unit for pascal Objects (not classes). Forces ''-s'' '+
|
||||
'Note: If -C or -O are not used then pascal Objects and consts '+
|
||||
'are in a single unit.');
|
||||
{$ENDIF CreatePascalClasses}
|
||||
AddOption(['N', 'no-wrappers'], False ,'Do not create wrappers for objects.');
|
||||
AddOption(['w', 'overwrite-files'], False ,'If the output .pas file(s) already exists then overwrite them.');
|
||||
AddOption(['n', 'no-default'], False ,'/usr/share/gir-1.0 is not added as a search location for needed .gir files.');
|
||||
AddOption(['p', 'paths'], True ,'List of paths seperated by ":" to search for needed .gir files.');
|
||||
AddOption(['d', 'deprecated'], False, 'Include fields and methods marked as deprecated.');
|
||||
AddOption(['t', 'test'], False ,'Creates a test program per unit to verify struct sizes.');
|
||||
AddOption(['P', 'unit-prefix'], True, 'Set a prefix to be added to each unitname.');
|
||||
AddOption(['M', 'max-version'], True, 'Do not include symbols introduced after <max-version>. Can be used multiple times. i.e "-M gtk-3.12 -M glib-2.23"');
|
||||
AddOption(['k', 'keep-deprecated-version'], True, 'Include deprecated symbols that are >= to $version. Uses the same format as --max-version. Has no effect if --deprecated is defined');
|
||||
end;
|
||||
FCmdOptions.ReadOptions;
|
||||
if FCmdOptions.OptionsMalformed then
|
||||
REsult := 'Error reading arguments';
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.DoRun;
|
||||
begin
|
||||
// quick check parameters
|
||||
CheckOptions;//('hnp:o:i:wtDCsO',['help','no-default','paths','output-directory', 'input', 'overwrite-files', 'test', 'dynamic', 'classes', 'seperate-units', 'objects']);
|
||||
|
||||
// parse parameters
|
||||
if FCmdOptions.OptionsMalformed then
|
||||
begin
|
||||
WriteLn('See -h for options.');
|
||||
Terminate;
|
||||
Halt;
|
||||
|
||||
end;
|
||||
|
||||
if FCmdOptions.HasOption('help') then begin
|
||||
WriteHelp;
|
||||
Terminate;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not FCmdOptions.HasOption('input') then
|
||||
begin
|
||||
WriteLn('No input file specified! See -h for options.');
|
||||
Terminate;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
if not FCmdOptions.HasOption('no-default') then
|
||||
AddDefaultPaths;
|
||||
|
||||
if FCmdOptions.HasOption('output-directory') then
|
||||
FOutPutDirectory:=IncludeTrailingPathDelimiter(FCmdOptions.OptionValue('output-directory'))
|
||||
else
|
||||
FOutPutDirectory:=IncludeTrailingPathDelimiter(GetCurrentDir);
|
||||
|
||||
FFileToConvert:=FCmdOptions.OptionValue('input');
|
||||
AddPaths(ExtractFilePath(FFileToConvert));
|
||||
|
||||
if FCmdOptions.HasOption('unit-prefix') then
|
||||
FUnitPrefix := FCmdOptions.OptionValue('unit-prefix');
|
||||
|
||||
if FCmdOptions.HasOption('paths') then
|
||||
AddPaths(FCmdOptions.OptionValue('paths'));
|
||||
|
||||
if FCmdOptions.HasOption('overwrite-files') then
|
||||
FOverWriteFiles:=True;
|
||||
|
||||
if FCmdOptions.HasOption('test') then
|
||||
Include(FOptions, goWantTest);
|
||||
|
||||
if FCmdOptions.HasOption('dynamic') then
|
||||
Include(FOptions, goLinkDynamic);
|
||||
|
||||
if FCmdOptions.HasOption('deprecated') then
|
||||
Include(FOptions, goIncludeDeprecated);
|
||||
|
||||
if FCmdOptions.HasOption('classes') then
|
||||
begin
|
||||
Include(FOptions, goClasses);
|
||||
Include(FOptions, goSeperateConsts);
|
||||
end;
|
||||
|
||||
if FCmdOptions.HasOption('no-wrappers') then
|
||||
Include(FOptions, goNoWrappers);
|
||||
|
||||
if FCmdOptions.HasOption('objects') then
|
||||
begin
|
||||
Include(FOptions, goObjects);
|
||||
Include(FOptions, goSeperateConsts);
|
||||
end;
|
||||
|
||||
if FCmdOptions.HasOption('seperate-units') then
|
||||
Include(FOptions, goSeperateConsts);
|
||||
|
||||
if FCmdOptions.HasOption('unit-prefix') then
|
||||
FUnitPrefix:=FCmdOptions.OptionValue('unit-prefix')
|
||||
else
|
||||
FUnitPrefix:='';
|
||||
|
||||
VerifyOptions;
|
||||
|
||||
// does all the heavy lifting
|
||||
Convert;
|
||||
|
||||
// stop program loop
|
||||
Terminate;
|
||||
end;
|
||||
|
||||
constructor TGirConsoleConverter.Create;
|
||||
begin
|
||||
//inherited Create(TheOwner);
|
||||
FCmdOptions := TCommandLineOptions.Create;
|
||||
FPaths := TStringList.Create;
|
||||
end;
|
||||
|
||||
destructor TGirConsoleConverter.Destroy;
|
||||
begin
|
||||
FPaths.Free;
|
||||
FCmdOptions.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.WriteHelp;
|
||||
var
|
||||
{$IFDEF UNIX}
|
||||
w: winsize;
|
||||
{$ENDIF}
|
||||
ConsoleWidth: Integer;
|
||||
begin
|
||||
ConsoleWidth:=80;
|
||||
{$IFDEF UNIX}
|
||||
fpioctl(0, TIOCGWINSZ, @w);
|
||||
ConsoleWidth:=w.ws_col;
|
||||
{$ENDIF}
|
||||
Writeln('Usage: ',ExtractFileName(ParamStr(0)),' [options] -i filename');
|
||||
with FCmdOptions.PrintHelp(ConsoleWidth) do
|
||||
begin
|
||||
WriteLn(Text);
|
||||
Free;
|
||||
end;
|
||||
{
|
||||
Writeln('');
|
||||
writeln(' Usage: ',ExtractFileName(ParamStr(0)),' [options] -i filename');
|
||||
Writeln('');
|
||||
Writeln('');
|
||||
Writeln(' -i --input= .gir filename to convert.');
|
||||
Writeln(' -o --output-directory= Directory to write the resulting .pas files to. If not');
|
||||
Writeln(' specified then the current working directory is used.');
|
||||
WriteLn(' -D --dynamic Use unit dynlibs and link at runtime');
|
||||
WriteLn(' -s --seperate-units Creates seperate units for each gir file:');
|
||||
WriteLn(' (xConsts, xTypes, xFunctions, [xClasses, xObjects].');
|
||||
WriteLn(' -C --classes Create Pascal classes that envelope/wrap the GObjects.');
|
||||
WriteLn(' Also forces ''-s''');
|
||||
WriteLn(' -O --objects OPTION NOT IMPLEMENTED YET. See Note below');
|
||||
WriteLn(' Creates a seperate unit for pascal Objects (not classes). Forces ''-s''');
|
||||
WriteLn(' Note: If -C or -O are not used then pascal Objects and consts');
|
||||
WriteLn(' are in a single unit.');
|
||||
Writeln(' -w --overwrite-files If the output .pas file(s) already exists then overwrite them.');
|
||||
Writeln(' -n --no-default /usr/share/gir-1.0 is not added as a search location for ');
|
||||
Writeln(' needed .gir files.');
|
||||
Writeln(' -p --paths= List of paths seperated by ":" to search for needed .gir files.');
|
||||
Writeln(' -t --test Creates a test program and a test c file per unit to verify struct sizes.');
|
||||
Writeln('');
|
||||
}
|
||||
end;
|
||||
procedure TGirConsoleConverter.Run;
|
||||
begin
|
||||
DoRun;
|
||||
end;
|
||||
|
||||
var
|
||||
Application: TGirConsoleConverter;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application:=TGirConsoleConverter.Create;
|
||||
Application.Run;
|
||||
Application.Free;
|
||||
end.
|
||||
|
BIN
tools/gir2pascal/gir2pascal.res
Normal file
BIN
tools/gir2pascal/gir2pascal.res
Normal file
Binary file not shown.
123
tools/gir2pascal/girctypesmapping.pas
Normal file
123
tools/gir2pascal/girctypesmapping.pas
Normal file
@ -0,0 +1,123 @@
|
||||
{
|
||||
ctypesmapping.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girCTypesMapping;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
CTypesMax = 34;
|
||||
var
|
||||
|
||||
TypesPascalCTypes: array [0..CTypesMax-1] of string =
|
||||
(
|
||||
'void',
|
||||
'pointer',
|
||||
'cint',
|
||||
'cint',
|
||||
'cuint',
|
||||
'cuint8',
|
||||
'cuint16',
|
||||
'cuint32',
|
||||
'cuint64',
|
||||
'cint8',
|
||||
'cint16',
|
||||
'cint32',
|
||||
'cint64',
|
||||
'csize_t',
|
||||
'clong',
|
||||
'culong',
|
||||
'cushort',
|
||||
'cshort',
|
||||
'char',
|
||||
'byte',
|
||||
'Boolean32',
|
||||
'PtrInt',
|
||||
'csize_t',
|
||||
'gpointer',
|
||||
'cfloat',
|
||||
'cdouble',
|
||||
'cdouble',
|
||||
'char',
|
||||
'Int64',
|
||||
'Extended',
|
||||
'guint32',
|
||||
'guint32',
|
||||
'file',
|
||||
'qword'
|
||||
|
||||
);
|
||||
TypesGTypes: array [0..CTypesMax-1] of string =
|
||||
(
|
||||
'void',
|
||||
'gpointer',
|
||||
'int',
|
||||
'gint',
|
||||
'guint',
|
||||
'guint8',
|
||||
'guint16',
|
||||
'guint32',
|
||||
'guint64',
|
||||
'gint8',
|
||||
'gint16',
|
||||
'gint32',
|
||||
'gint64',
|
||||
'gsize',
|
||||
'glong',
|
||||
'gulong',
|
||||
'gushort',
|
||||
'gshort',
|
||||
'gchar',
|
||||
'guchar',
|
||||
'gboolean',
|
||||
'gssize',
|
||||
'size_t' ,
|
||||
'gconstpointer',
|
||||
'gfloat',
|
||||
'gdouble',
|
||||
'double',
|
||||
'char',
|
||||
'goffset',
|
||||
'long double',
|
||||
'gunichar',
|
||||
'gunichar2',
|
||||
'file',
|
||||
'unsigned long long'
|
||||
);
|
||||
|
||||
function LookupGTypeToCType(AName: String): String;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function LookupGTypeToCType(AName: String): String;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
//WriteLn('Looking up: ', AName);
|
||||
for i := 0 to CTypesMax-1 do
|
||||
if AName = TypesGTypes[i] then
|
||||
Exit(TypesPascalCTypes[i]);
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
end.
|
||||
|
86
tools/gir2pascal/girerrors.pas
Normal file
86
tools/gir2pascal/girerrors.pas
Normal file
@ -0,0 +1,86 @@
|
||||
{
|
||||
girerrors.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girErrors;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
type
|
||||
TGirError = (geError, geWarn, geInfo, geDebug, geFatal, geFuzzy);
|
||||
|
||||
TgirErrorFunc = procedure(UserData: Pointer; AType: TgirError; AMsg: String);
|
||||
|
||||
const
|
||||
geUnhandledNode = 'Unhandled node [%s] "%s"';
|
||||
geUnexpectedNodeType = 'Unexpected node [%s] type: found "%s" expected "%s"';
|
||||
geMissingNode = '[%s] Could not find child node "%s" while looking in node "%s"';
|
||||
geAddingErrorNode = '%s %s throws an error but is not included as a param. Adding...';
|
||||
|
||||
var
|
||||
girErrorName: array[TGirError] of String =(
|
||||
'Error',
|
||||
'Warning',
|
||||
'Info',
|
||||
'Debug',
|
||||
'Fatal',
|
||||
'Fuzzy'
|
||||
);
|
||||
procedure girError(AType: TgirError; AMsg: String);
|
||||
procedure girError(AType: TgirError; const Fmt: string; const Args: array of Const);
|
||||
|
||||
//returns old handler
|
||||
function girSetErrorHandler(AHandler: TgirErrorFunc; AUserData: Pointer): TgirErrorFunc;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
UserData: Pointer;
|
||||
InternalHandler: TgirErrorFunc;
|
||||
|
||||
procedure girError(AType: TgirError; AMsg: String);
|
||||
begin
|
||||
if InternalHandler <> nil then
|
||||
begin
|
||||
InternalHandler(UserData, AType, AMsg);
|
||||
Exit;
|
||||
end;
|
||||
// if AType = geDebug then
|
||||
WriteLn(girErrorName[AType],': ', AMsg);
|
||||
|
||||
end;
|
||||
|
||||
procedure girError(AType: TgirError; const Fmt: string; const Args: array of Const);
|
||||
begin
|
||||
girError(AType, Format(Fmt, Args));
|
||||
end;
|
||||
|
||||
function girSetErrorHandler(AHandler: TgirErrorFunc; AUserData: Pointer
|
||||
): TgirErrorFunc;
|
||||
begin
|
||||
Result := InternalHandler;
|
||||
InternalHandler:=AHandler;
|
||||
UserData:=AUserData;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
211
tools/gir2pascal/girfiles.pas
Normal file
211
tools/gir2pascal/girfiles.pas
Normal file
@ -0,0 +1,211 @@
|
||||
{
|
||||
girfiles.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girFiles;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$INTERFACES CORBA}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, DOM, girNameSpaces, girParser, CommandLineOptions;
|
||||
|
||||
type
|
||||
|
||||
{ TgirFile }
|
||||
|
||||
TgirFile = class(IgirParser)
|
||||
private
|
||||
FNameSpaces: TgirNamespaces;
|
||||
FOnNeedGirFile: TgirNeedGirFileEvent;
|
||||
FOwner: TObject;
|
||||
FCmdOptions: TCommandLineOptions;
|
||||
procedure ParseNode(ANode: TDomNode);
|
||||
procedure SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
procedure SetOwner(const AValue: TObject);
|
||||
procedure ParseIncludeNode(ANode: TDomNode; AIncludes: TList);
|
||||
procedure CheckVersionLimits(const ANameSpace: TgirNamespace);
|
||||
function CheckVersionOptions(const ANamespace: String; var AMajor, AMinor: Integer): Boolean;
|
||||
public
|
||||
constructor Create(AOwner: TObject; AOptions: TCommandLineOptions);
|
||||
destructor Destroy; override;
|
||||
procedure ParseXMLDocument(AXML: TXMLDocument);
|
||||
property NameSpaces: TgirNamespaces read FNameSpaces;
|
||||
property Owner: TObject read FOwner write SetOwner; // TGirConsoleConverter
|
||||
property OnNeedGirFile: TgirNeedGirFileEvent read FOnNeedGirFile write SetOnNeedGirFile;
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
uses girErrors, girTokens;
|
||||
|
||||
{ TgirFile }
|
||||
|
||||
|
||||
{ TgirFile }
|
||||
|
||||
procedure TgirFile.ParseNode(ANode: TDomNode);
|
||||
var
|
||||
Node: TDomNode;
|
||||
NS: TgirNamespace;
|
||||
Includes: TList;
|
||||
begin
|
||||
if ANode.NodeName <> 'repository' then
|
||||
girError(geError, 'Not a Valid Document Type!');
|
||||
|
||||
Node := Anode.FirstChild;
|
||||
Ns := nil;
|
||||
Includes := TList.Create;
|
||||
|
||||
while Node <> nil do begin
|
||||
case GirTokenNameToToken(Node.NodeName) of
|
||||
gtInclude: ParseIncludeNode(Node, Includes);
|
||||
gtNameSpace:
|
||||
begin
|
||||
NS := TgirNamespace.CreateFromRepositoryNode(NameSpaces, ANode, Includes);
|
||||
girError(geDebug, 'Adding Namespace '+NS.NameSpace+' to NameSpaces');
|
||||
FNameSpaces.Add(NS);
|
||||
girError(geDebug, 'Added Namespace '+NS.NameSpace);
|
||||
CheckVersionLimits(NS);
|
||||
NS.ParseNode(Node);
|
||||
end;
|
||||
gtPackage, gtCInclude: ;// ignore for now
|
||||
else
|
||||
girError(geDebug, 'Unknown Node Type for Reposiotory: '+ node.NodeName);
|
||||
end;
|
||||
Node := Node.NextSibling;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ANode := ANode.FindNode('namespace');
|
||||
if ANode = nil then
|
||||
girError(geError, 'namespace node not found')
|
||||
else
|
||||
begin
|
||||
|
||||
end;}
|
||||
end;
|
||||
|
||||
procedure TgirFile.SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
begin
|
||||
FNameSpaces.OnNeedGirFile:=AValue;
|
||||
if FOnNeedGirFile=AValue then Exit;
|
||||
FOnNeedGirFile:=AValue;
|
||||
end;
|
||||
|
||||
procedure TgirFile.SetOwner(const AValue: TObject);
|
||||
begin
|
||||
if FOwner=AValue then exit;
|
||||
FOwner:=AValue;
|
||||
end;
|
||||
|
||||
procedure TgirFile.ParseIncludeNode(ANode: TDomNode; AIncludes: TList);
|
||||
var
|
||||
NS: TgirNamespace;
|
||||
NSName, NSVersion: String;
|
||||
begin
|
||||
NSName := TDOMElement(ANode).GetAttribute('name');
|
||||
NSVersion := TDOMElement(ANode).GetAttribute('version');
|
||||
NS := FNameSpaces.FindNameSpace(NSName, NSVersion);
|
||||
if NS <> nil then
|
||||
begin
|
||||
AIncludes.Add(NS);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TgirFile.CheckVersionLimits(const ANameSpace: TgirNamespace);
|
||||
|
||||
|
||||
function SplitVersion(AVersionStr: String; out AVersion: TGirVersion): Boolean;
|
||||
begin
|
||||
try
|
||||
AVersion := girVersion(AVersionStr);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function SplitNameSpaceVersionCheck(AOptionName: String; var AVersion: TGirVersion): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if FCmdOptions.HasOption(AOptionName) then
|
||||
with FCmdOptions.OptionValues(AOptionName) do
|
||||
begin
|
||||
for i := 0 to Count-1 do
|
||||
begin
|
||||
if Lowercase(ANameSpace.NameSpace)+'-' = Lowercase(Copy(Strings[i], 1, Length(ANameSpace.NameSpace)+1)) then
|
||||
begin
|
||||
Result := SplitVersion(Copy(Strings[i], Length(ANameSpace.NameSpace)+2, MaxInt), AVersion);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
lVersion: TGirVersion;
|
||||
begin
|
||||
if SplitNameSpaceVersionCheck('max-version', lVersion) then
|
||||
ANameSpace.MaxSymbolVersion := lVersion
|
||||
else
|
||||
ANameSpace.MaxSymbolVersion := girVersion(MaxInt, MaxInt);
|
||||
|
||||
|
||||
if SplitNameSpaceVersionCheck('keep-deprecated-version', lVersion) then
|
||||
ANameSpace.DeprecatedVersion := lVersion
|
||||
else
|
||||
ANameSpace.DeprecatedVersion := girVersion(MaxInt, MaxInt);
|
||||
|
||||
|
||||
end;
|
||||
|
||||
function TgirFile.CheckVersionOptions(const ANamespace: String; var AMajor, AMinor: Integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
constructor TgirFile.Create(AOwner: TObject; AOptions: TCommandLineOptions);
|
||||
begin
|
||||
Owner := AOwner;
|
||||
FCmdOptions := AOptions;
|
||||
FNameSpaces := TgirNamespaces.Create(Self);
|
||||
end;
|
||||
|
||||
destructor TgirFile.Destroy;
|
||||
begin
|
||||
FNameSpaces.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TgirFile.ParseXMLDocument(AXML: TXMLDocument);
|
||||
begin
|
||||
Self.ParseNode(AXML.DocumentElement);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
618
tools/gir2pascal/girnamespaces.pas
Normal file
618
tools/gir2pascal/girnamespaces.pas
Normal file
@ -0,0 +1,618 @@
|
||||
{
|
||||
girnamespaces.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girNameSpaces;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$INTERFACES CORBA}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, DOM, girParser, girTokens, girObjects, contnrs;
|
||||
|
||||
type
|
||||
|
||||
TgirNeedGirFileEvent = function (AGirFile: TObject; BaseNamespaceName: String) : TXMLDocument of object;
|
||||
|
||||
{ TgirNamespace }
|
||||
|
||||
TgirNamespace = class(IgirParser)
|
||||
private
|
||||
FCIncludeName: String;
|
||||
FConstants: TList;
|
||||
FCPackageName: String;
|
||||
FCPrefix: String;
|
||||
FDeprecatedVersion: TGirVersion;
|
||||
FFunctions: TList;
|
||||
FMaxSymbolVersion: TGirVersion;
|
||||
FNameSpace: String;
|
||||
FOnlyImplied: Boolean;
|
||||
FOnNeedGirFile: TgirNeedGirFileEvent;
|
||||
FOwner: TObject;
|
||||
FRequiredNameSpaces: TList;
|
||||
FSharedLibrary: String;
|
||||
FTypes: TFPHashObjectList;
|
||||
FUnresolvedTypes: TList;
|
||||
FVersion: TGirVersion;
|
||||
procedure SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
protected
|
||||
function AddFuzzyType(AName: String; ACType: String): TGirBaseType;
|
||||
procedure HandleAlias(ANode: TDomNode);
|
||||
procedure HandleConstant(ANode: TDomNode);
|
||||
procedure HandleEnumeration(ANode: TDomNode);
|
||||
procedure HandleBitField(ANode: TDomNode);
|
||||
procedure HandleCallback(ANode: TDOMNode);
|
||||
procedure HandleFunction(ANode: TDOMNode);
|
||||
procedure HandleUnion(ANode: TDOMNode);
|
||||
{
|
||||
Some 'records' have methods these corelate to pascal 'object'
|
||||
GType extends this 'object' type to have a sort of vmt
|
||||
GObject and subclasses extend gtype and adds more vmt method entries and method entries to the instance itself.
|
||||
}
|
||||
procedure HandleRecord(ANode: TDomNode); //could be struct, object, gtype, gobject, or gobject descendant
|
||||
procedure HandlePlainObject(ANode: TDomNode); // is a record/object with methods but no gtype
|
||||
procedure HandleGType(ANode: TDomNode); // one step above plain object
|
||||
procedure HandleClassStruct(ANode: TDomNode); // one step above GType. Is the 'Virtual' part of an object (VMT)
|
||||
procedure HandleClass(ANode: TDomNode); // one step above GType. Is the object structure and it's methods. ClassStruct is like the VMT
|
||||
procedure HandleInterface(ANode: TDomNode);
|
||||
procedure AddGLibBaseTypes;
|
||||
public
|
||||
procedure AddType(AType: TGirBaseType);
|
||||
function LookupTypeByName(AName: String; const ACType: String; SearchOnly: Boolean = False): TGirBaseType;
|
||||
function ResolveFuzzyType(AFuzzyType: TgirFuzzyType): TGirBaseType;
|
||||
function UsesGLib: Boolean;
|
||||
procedure ResolveFuzzyTypes; // called after done
|
||||
procedure ParseNode(ANode: TDomNode);
|
||||
procedure ParseSubNode(ANode: TDomNode); // generally do not use outside of TgirNameSpace
|
||||
constructor Create(AOwner:TObject; AImpliedNamespace: String);
|
||||
constructor CreateFromRepositoryNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList);
|
||||
destructor Destroy; override;
|
||||
property NameSpace: String read FNameSpace;
|
||||
property CIncludeName: String read FCIncludeName;
|
||||
property CPackageName: String read FCPackageName;
|
||||
property CPrefix: String read FCPrefix;
|
||||
property RequiredNameSpaces: TList Read FRequiredNameSpaces;
|
||||
property SharedLibrary: String read FSharedLibrary;
|
||||
property Version: TGirVersion read FVersion;
|
||||
property OnlyImplied: Boolean read FOnlyImplied;
|
||||
property Owner: TObject Read FOwner;
|
||||
|
||||
// has all types in it (records classes classstructs bitfields callbacks gtypes unions etc) does not contain consts or functions
|
||||
property Types: TFPHashObjectList read FTypes;
|
||||
|
||||
property Functions: TList read FFunctions;
|
||||
property Constants: TList read FConstants;
|
||||
property UnresolvedTypes: TList read FUnresolvedTypes write FUnresolvedTypes;
|
||||
// exclude symbols newer than this version
|
||||
property MaxSymbolVersion: TGirVersion read FMaxSymbolVersion write FMaxSymbolVersion;
|
||||
// exclude symbols this version and older that are marked as deprecated
|
||||
property DeprecatedVersion: TGirVersion read FDeprecatedVersion write FDeprecatedVersion;
|
||||
end;
|
||||
|
||||
{ TgirNamespaces }
|
||||
|
||||
TgirNamespaces = class(TList)
|
||||
private
|
||||
FOnNeedGirFile: TgirNeedGirFileEvent;
|
||||
FOwner: TObject;
|
||||
function GetNameSpace(AIndex: Integer): TgirNamespace;
|
||||
procedure SetNameSpace(AIndex: Integer; const AValue: TgirNamespace);
|
||||
procedure SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
public
|
||||
constructor Create(AOwner: TObject);
|
||||
function FindNameSpace(AName: String; Version: String = ''): TgirNamespace;
|
||||
property NameSpace[AIndex: Integer]: TgirNamespace read GetNameSpace write SetNameSpace;
|
||||
property Owner: TObject read FOwner;
|
||||
property OnNeedGirFile: TgirNeedGirFileEvent read FOnNeedGirFile write SetOnNeedGirFile;
|
||||
end;
|
||||
|
||||
implementation
|
||||
uses
|
||||
girErrors, SysUtils, girCTypesMapping;
|
||||
|
||||
{ TgirNamespaces }
|
||||
|
||||
function TgirNamespaces.GetNameSpace(AIndex: Integer): TgirNamespace;
|
||||
begin
|
||||
Result := TgirNamespace(Items[AIndex]);
|
||||
end;
|
||||
|
||||
procedure TgirNamespaces.SetNameSpace(AIndex: Integer;
|
||||
const AValue: TgirNamespace);
|
||||
begin
|
||||
Items[AIndex] := AValue;
|
||||
end;
|
||||
|
||||
procedure TgirNamespaces.SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
begin
|
||||
if FOnNeedGirFile=AValue then Exit;
|
||||
FOnNeedGirFile:=AValue;
|
||||
end;
|
||||
|
||||
constructor TgirNamespaces.Create(AOwner: TObject);
|
||||
begin
|
||||
FOwner := AOwner;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
function TgirNamespaces.FindNameSpace(AName: String; Version: String=''): TgirNamespace;
|
||||
var
|
||||
i: Integer;
|
||||
NameSpaceSearchedFor: Boolean;
|
||||
Doc: TXMLDocument;
|
||||
begin
|
||||
Result := nil;
|
||||
NameSpaceSearchedFor := False;
|
||||
while Result = nil do
|
||||
begin
|
||||
for i := 0 to Count-1 do
|
||||
begin
|
||||
if NameSpace[i].NameSpace = AName then
|
||||
Exit(NameSpace[i]);
|
||||
end;
|
||||
|
||||
if NameSpaceSearchedFor then
|
||||
Exit;
|
||||
NameSpaceSearchedFor := True;
|
||||
if Assigned(FOnNeedGirFile) then
|
||||
begin
|
||||
Doc := FOnNeedGirFile(Owner, AName+'-'+Version);
|
||||
if Doc <> nil then
|
||||
begin
|
||||
(Owner as IgirParser).ParseNode(Doc.DocumentElement);
|
||||
Doc.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TgirNamespace }
|
||||
|
||||
procedure TgirNamespace.ParseNode(ANode: TDomNode);
|
||||
|
||||
begin
|
||||
ANode := ANode.FirstChild;
|
||||
while ANode <> nil do
|
||||
begin
|
||||
//girError(geDebug, 'Parsing Node "'+ANode.NodeName+'"');
|
||||
ParseSubNode(ANode);
|
||||
ANode := ANode.NextSibling;
|
||||
end;
|
||||
ResolveFuzzyTypes;
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.SetOnNeedGirFile(AValue: TgirNeedGirFileEvent);
|
||||
begin
|
||||
if FOnNeedGirFile=AValue then Exit;
|
||||
FOnNeedGirFile:=AValue;
|
||||
end;
|
||||
|
||||
function TgirNamespace.AddFuzzyType(AName: String; ACType: String
|
||||
): TGirBaseType;
|
||||
begin
|
||||
Result := TgirFuzzyType.Create(Self, AName, ACType);
|
||||
AddType(Result);
|
||||
FUnresolvedTypes.Add(Result);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleAlias(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirAlias;
|
||||
begin
|
||||
Item := TgirAlias.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleConstant(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirConstant;
|
||||
begin
|
||||
Item := TgirConstant.Create(Self, ANode);
|
||||
FConstants.Add(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleEnumeration(ANode: TDomNode);
|
||||
var
|
||||
Item : TgirEnumeration;
|
||||
begin
|
||||
Item := TgirEnumeration.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleBitField(ANode: TDomNode);
|
||||
var
|
||||
Item : TgirBitField;
|
||||
begin
|
||||
Item := TgirBitField.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleCallback(ANode: TDOMNode);
|
||||
var
|
||||
Item: TgirCallback;
|
||||
begin
|
||||
Item := TgirCallback.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleFunction(ANode: TDOMNode);
|
||||
var
|
||||
Item: TgirFunction;
|
||||
begin
|
||||
Item := TgirFunction.Create(Self, ANode);
|
||||
Functions.Add(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleUnion(ANode: TDOMNode);
|
||||
var
|
||||
Item: TgirUnion;
|
||||
begin
|
||||
Item := TgirUnion.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleRecord(ANode: TDomNode);
|
||||
var
|
||||
Item: tgirRecord;
|
||||
begin
|
||||
if TDOMElement(ANode).GetAttribute('glib:is-gtype-struct-for') <> '' then // is gobject class
|
||||
begin
|
||||
HandleClassStruct(ANode);
|
||||
end
|
||||
else if TDOMElement(ANode).GetAttribute('glib:get-type') <> '' then // is GType
|
||||
HandleGType(ANode)
|
||||
else if (ANode.FindNode('method') <> nil) or (ANode.FindNode('constructor') <> nil) or (ANode.FindNode('function') <> nil) then // is Plain object that is not gtype
|
||||
HandlePlainObject(ANode)
|
||||
else
|
||||
begin
|
||||
Item := tgirRecord.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandlePlainObject(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirObject;
|
||||
begin
|
||||
Item := TgirObject.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleGType(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirGType;
|
||||
begin
|
||||
Item := TgirGType.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleClassStruct(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirClassStruct;
|
||||
begin
|
||||
Item := TgirClassStruct.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleClass(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirClass;
|
||||
begin
|
||||
Item := TgirClass.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.HandleInterface(ANode: TDomNode);
|
||||
var
|
||||
Item: TgirInterface;
|
||||
begin
|
||||
Item := TgirInterface.Create(Self, ANode);
|
||||
AddType(Item);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.AddGLibBaseTypes;
|
||||
function AddNativeTypeDef(GType: String; PascalCName: String; TranslatedName: String): TgirNativeTypeDef;
|
||||
var
|
||||
NativeType: TgirNativeTypeDef;
|
||||
begin
|
||||
NativeType:= TgirNativeTypeDef.Create(Self, GType, PascalCName);
|
||||
if TranslatedName <> '' then
|
||||
NativeType.TranslatedName:=TranslatedName;
|
||||
NativeType.ImpliedPointerLevel:=3;
|
||||
AddType(NativeType);
|
||||
Result := NativeType;
|
||||
|
||||
end;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to CTypesMax-1 do
|
||||
AddNativeTypeDef(TypesGTypes[i], TypesPascalCTypes[i], '');
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.AddType(AType: TGirBaseType);
|
||||
var
|
||||
PrevFound: TGirBaseType = nil;
|
||||
begin
|
||||
PrevFound := TGirBaseType(FTypes.Find(AType.Name));
|
||||
if (PrevFound <> nil) and (PrevFound.ObjectType = otFuzzyType) then
|
||||
begin
|
||||
(PrevFound as TgirFuzzyType).ResolvedType := AType;
|
||||
//WriteLn('Resolved FuzzyType: ', AType.Name);
|
||||
FUnresolvedTypes.Remove(PrevFound);
|
||||
end;
|
||||
//if PrevFound <> nil then WriteLn('Found Name Already Added: ', AType.Name, ' ', PrevFound.ObjectType, ' ', AType.ObjectType);
|
||||
if PrevFound = nil then
|
||||
FTypes.Add(AType.Name, AType);
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.ResolveFuzzyTypes;
|
||||
var
|
||||
i: Integer;
|
||||
FuzzyI: Integer;
|
||||
Fuzzy: TgirFuzzyType;
|
||||
FuzzyP: Pointer absolute Fuzzy;
|
||||
Tmp: TGirBaseType;
|
||||
StillFuzzy: TList;
|
||||
Current: TGirBaseType;
|
||||
ReqNS: TgirNamespace;
|
||||
begin
|
||||
i:= 0;
|
||||
FuzzyI := 0;
|
||||
Fuzzy := nil;
|
||||
StillFuzzy := TList.Create;
|
||||
while (i < FTypes.Count) or (Fuzzy <> nil) do
|
||||
begin
|
||||
// make our loop safe
|
||||
if i >= FTypes.Count then
|
||||
begin
|
||||
i := FuzzyI+1;
|
||||
StillFuzzy.Add(Fuzzy);
|
||||
Fuzzy := nil;
|
||||
continue;
|
||||
end;
|
||||
|
||||
Tmp := TGirBaseType(FTypes.Items[i]);
|
||||
|
||||
if Fuzzy <> nil then
|
||||
begin
|
||||
if {(Tmp.CType = Fuzzy.CType) or} (Tmp.Name = Fuzzy.Name) then
|
||||
begin
|
||||
Fuzzy.ResolvedType := Tmp;
|
||||
Tmp.ImpliedPointerLevel:=Fuzzy.ImpliedPointerLevel;
|
||||
Tmp.DeprecatedOverride:= Tmp.DeprecatedOverride or Fuzzy.DeprecatedOverride;
|
||||
i := FuzzyI+1;
|
||||
Fuzzy := nil;
|
||||
//WriteLn('Resolved Fuzzy Type: ', Tmp.CType);
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (Fuzzy = nil) and (Tmp.ObjectType = otFuzzyType) and (TgirFuzzyType(Tmp).ResolvedType = nil) then
|
||||
begin
|
||||
if i >= FTypes.Count then
|
||||
break;
|
||||
FuzzyI:=i;
|
||||
Fuzzy := TgirFuzzyType(Tmp);
|
||||
//WriteLn('Looking For: ',Fuzzy.CType);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
// if the types are still fuzzy then we will search used namespaces for what we want
|
||||
for FuzzyP in StillFuzzy do //FuzzyP is Fuzzy absolute
|
||||
begin
|
||||
if Fuzzy.ResolvedType <> nil then
|
||||
continue;
|
||||
for i := 0 to RequiredNameSpaces.Count-1 do
|
||||
begin
|
||||
ReqNS := TgirNamespace(RequiredNameSpaces.Items[i]);
|
||||
Current := ReqNS.LookupTypeByName(Fuzzy.Name, '', True);
|
||||
if Current <> nil then
|
||||
begin
|
||||
if (Current.ObjectType = otFuzzyType) and (TgirFuzzyType(Current).ResolvedType <> nil) then
|
||||
Current := TgirFuzzyType(Current).ResolvedType;
|
||||
Fuzzy.ResolvedType := Current;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
StillFuzzy.Free;
|
||||
end;
|
||||
|
||||
procedure TgirNamespace.ParseSubNode(ANode: TDomNode);
|
||||
begin
|
||||
case GirTokenNameToToken(ANode.NodeName) of
|
||||
gtAlias: HandleAlias(ANode);
|
||||
gtConstant: HandleConstant(ANode);
|
||||
gtRecord: HandleRecord(ANode);
|
||||
gtBitField: HandleBitField(ANode);
|
||||
gtEnumeration: HandleEnumeration(ANode);
|
||||
gtCallback: HandleCallback(ANode);
|
||||
gtUnion: HandleUnion(ANode);
|
||||
gtFunction: HandleFunction(ANode);
|
||||
gtClass: HandleClass(ANode);
|
||||
gtInterface: HandleInterface(ANode);
|
||||
gtMethod: HandleFunction(ANode);
|
||||
else
|
||||
girError(geError, 'Unknown NodeType: '+ANode.NodeName);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TgirNamespace.LookupTypeByName(AName: String; const ACType: String; SearchOnly: Boolean = False): TGirBaseType;
|
||||
function StripPointers(ACPointeredType: String; PtrLevel: PInteger = nil): String;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := Length(ACPointeredType) downto 1 do
|
||||
if ACPointeredType[i] = '*' then
|
||||
begin
|
||||
Delete(ACPointeredType, i, 1);
|
||||
end;
|
||||
if PtrLevel <> nil then
|
||||
Inc(PtrLevel^);
|
||||
Result := ACPointeredType;
|
||||
end;
|
||||
|
||||
var
|
||||
NS: TgirNamespace;
|
||||
NSString: String;
|
||||
FPos: Integer;
|
||||
PointerLevel: Integer = 0;
|
||||
PlainCType: String;
|
||||
begin
|
||||
Result := nil;
|
||||
NS := Self;
|
||||
// some basic fixes
|
||||
PlainCType:=StringReplace(StripPointers(ACType, @PointerLevel), ' ', '_', [rfReplaceAll]);
|
||||
if (PlainCType = 'gchar') or {(PlainCType = 'guchar') or} (PlainCType = 'char') or (PlainCType = 'const_char') then
|
||||
AName := 'GLib.utf8';
|
||||
|
||||
if (PlainCType = 'GType') {or (AName = 'Type')} or (AName = 'GType')then
|
||||
AName := 'GLib.Type';
|
||||
|
||||
if AName = 'any' then
|
||||
AName := 'gpointer';
|
||||
|
||||
FPos := Pos('.', AName);
|
||||
|
||||
if FPos > 0 then // type includes namespace "NameSpace.Type"
|
||||
begin
|
||||
NSString:=Copy(AName,1,FPos-1);
|
||||
|
||||
//NS := (Owner As TgirNamespaces).FindNameSpace(NSString);
|
||||
NS := TgirNamespaces(Owner).FindNameSpace(NSString);
|
||||
if NS = nil then
|
||||
girError(geError, 'Referenced Namespace "'+NSString+'" not found while looking for '+AName);
|
||||
AName := Copy(AName, FPos+1, Length(AName));
|
||||
end;
|
||||
|
||||
if NS <> Self then SearchOnly:=True;
|
||||
|
||||
//if NS <> Self then WriteLn('Self NS = ', NameSpace, ' Lookup NS = ', NS.NameSpace);
|
||||
Result := TGirBaseType(NS.Types.Find(AName));
|
||||
if (Result <> nil) and (Result.ObjectType = otFuzzyType) and (TgirFuzzyType(Result).ResolvedType <> nil) then
|
||||
Result := TgirFuzzyType(Result).ResolvedType;
|
||||
|
||||
// if we find a result in another namespace then we need to depend on that namespace/unit
|
||||
if (NS <> nil) and (NS <> Self) and (Result <> nil) then
|
||||
if FRequiredNameSpaces.IndexOf(NS) = -1 then
|
||||
FRequiredNameSpaces.Add(NS);
|
||||
|
||||
if (Result = nil) and Not SearchOnly then
|
||||
Result := NS.AddFuzzyType(AName, ACType);
|
||||
if Result <> nil then
|
||||
Result.ImpliedPointerLevel:=PointerLevel;
|
||||
|
||||
end;
|
||||
|
||||
function TgirNamespace.ResolveFuzzyType(AFuzzyType: TgirFuzzyType): TGirBaseType;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to FTypes.Count-1 do
|
||||
begin
|
||||
if (TGirBaseType(FTypes[i]) <> AFuzzyType) and (TGirBaseType(FTypes[i]).Name = AFuzzyType.Name) then
|
||||
Exit(TGirBaseType(FTypes[i]));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TgirNamespace.UsesGLib: Boolean;
|
||||
var
|
||||
Tmp: Pointer;
|
||||
NS: TgirNamespace absolute Tmp;
|
||||
begin
|
||||
Result := False;
|
||||
if Pos('glib', LowerCase(NameSpace)) = 1 then
|
||||
Exit(True);
|
||||
for Tmp in RequiredNameSpaces do
|
||||
if Pos('glib',LowerCase(NS.NameSpace)) = 1 then
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
constructor TgirNamespace.Create(AOwner:TObject; AImpliedNamespace: String);
|
||||
begin
|
||||
Fowner:=AOwner;
|
||||
FOnlyImplied:=True;
|
||||
FNameSpace:=AImpliedNamespace;
|
||||
girError(geDebug, 'Creating Stub for namespace: '+ AImpliedNamespace);
|
||||
end;
|
||||
|
||||
constructor TgirNamespace.CreateFromRepositoryNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList);
|
||||
procedure SetCInclude;
|
||||
var
|
||||
Child: TDomElement;
|
||||
begin
|
||||
Child := TDOMElement(ANode.FindNode('c:include name'));
|
||||
if (Child <> nil) and Child.InheritsFrom(TDOMElement) then
|
||||
FCIncludeName:= Child.GetAttribute('name');
|
||||
end;
|
||||
procedure SetPackage;
|
||||
var
|
||||
Child: TDOMElement;
|
||||
begin
|
||||
Child := TDOMElement(ANode.FindNode('package'));
|
||||
if (Child <> nil) and Child.InheritsFrom(TDOMElement) then
|
||||
FCPackageName:=Child.GetAttribute('name');
|
||||
end;
|
||||
|
||||
var
|
||||
Node: TDOMElement;
|
||||
begin
|
||||
FOwner := AOwner;
|
||||
if ANode = nil then
|
||||
girError(geError, 'expected namespace got nil');
|
||||
if ANode.NodeName <> 'repository' then
|
||||
girError(geError, 'expected "repository" got '+ANode.NodeName);
|
||||
Node := TDOMElement( ANode.FindNode('namespace') );
|
||||
FNameSpace:=Node.GetAttribute('name');
|
||||
FRequiredNameSpaces := AIncludes;
|
||||
FSharedLibrary:=Node.GetAttribute('shared-library');
|
||||
FVersion:=girVersion(Node.GetAttribute('version'));
|
||||
FCPrefix:=Node.GetAttribute('c:prefix');
|
||||
SetCInclude;
|
||||
SetPackage;
|
||||
girError(geDebug, Format('Creating namespace=%s Version=%s LibName=%s',[FNameSpace, FVersion.AsString, FSharedLibrary]));
|
||||
|
||||
FConstants := TList.Create;
|
||||
FFunctions := TList.Create;
|
||||
FTypes := TFPHashObjectList.Create(True);
|
||||
FUnresolvedTypes := TList.Create;
|
||||
|
||||
FMaxSymbolVersion.Major:=MaxInt;
|
||||
|
||||
if FNameSpace = 'GLib' then
|
||||
AddGLibBaseTypes;
|
||||
end;
|
||||
|
||||
destructor TgirNamespace.Destroy;
|
||||
begin
|
||||
FConstants.Free;
|
||||
FFunctions.Free;
|
||||
FTypes.Free;
|
||||
FUnresolvedTypes.Free;
|
||||
if Assigned(FRequiredNameSpaces) then
|
||||
FRequiredNameSpaces.Free;
|
||||
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
1442
tools/gir2pascal/girobjects.pas
Normal file
1442
tools/gir2pascal/girobjects.pas
Normal file
File diff suppressed because it is too large
Load Diff
18
tools/gir2pascal/girparser.pas
Normal file
18
tools/gir2pascal/girparser.pas
Normal file
@ -0,0 +1,18 @@
|
||||
unit girParser;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$INTERFACES CORBA}
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Dom;
|
||||
|
||||
type
|
||||
IgirParser = interface
|
||||
procedure ParseNode(ANode: TDomNode);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
42
tools/gir2pascal/girpascalclasswriter.pas
Normal file
42
tools/gir2pascal/girpascalclasswriter.pas
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
The purpose of this unit is to create native pascal classes that wrap gobjects in a comfortable and usable way.
|
||||
}
|
||||
|
||||
|
||||
unit girPascalClassWriter;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, girObjects, girpascalwriter, girpascalwritertypes;
|
||||
|
||||
type
|
||||
|
||||
{ TGObjectClass }
|
||||
|
||||
TGObjectClass = class
|
||||
private
|
||||
FParentGObjectClass: TGObjectClass;
|
||||
FgirObject: TgirClass;
|
||||
FPascalUnit: TPascalUnit;
|
||||
public
|
||||
constructor Create(AParentGObjectClass: TGObjectClass; AClass: TgirClass; APascalUnit: TPascalUnit);
|
||||
property ParentGObjectClass: TGObjectClass read FParentGObjectClass;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ TGObjectClass }
|
||||
|
||||
constructor TGObjectClass.Create(AParentGObjectClass: TGObjectClass; AClass: TgirClass; APascalUnit: TPascalUnit);
|
||||
begin
|
||||
FParentGObjectClass := AParentGObjectClass;
|
||||
FgirObject := AClass;
|
||||
FPascalUnit:=APascalUnit;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
82
tools/gir2pascal/girpascalwriter.pas
Normal file
82
tools/gir2pascal/girpascalwriter.pas
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
girpascalwriter.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girpascalwriter;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,girNameSpaces, girpascalwritertypes;
|
||||
|
||||
type
|
||||
|
||||
|
||||
{ TgirPascalWriter }
|
||||
|
||||
TgirPascalWriter = class
|
||||
private
|
||||
FDefaultUnitExtension: String;
|
||||
FUnitPrefix: String;
|
||||
FOnUnitWriteEvent: TgirWriteEvent;
|
||||
FNameSpaces: TgirNamespaces;
|
||||
FUnits: TList;
|
||||
FOptions: TgirOptions;
|
||||
public
|
||||
constructor Create(ANameSpaces: TgirNamespaces; AOptions: TgirOptions; AUnitPrefix: String);
|
||||
procedure GenerateUnits;
|
||||
property OnUnitWriteEvent: TgirWriteEvent read FOnUnitWriteEvent write FOnUnitWriteEvent;
|
||||
property DefaultUnitExtension: String read FDefaultUnitExtension write FDefaultUnitExtension; // is .pas by default
|
||||
property Units: TList read FUnits;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
uses girCTypesMapping;
|
||||
|
||||
|
||||
{ TgirPascalWriter }
|
||||
|
||||
constructor TgirPascalWriter.Create(ANameSpaces: TgirNamespaces; AOptions: TgirOptions; AUnitPrefix: String);
|
||||
begin
|
||||
FNameSpaces := ANameSpaces;
|
||||
FUnitPrefix := AUnitPrefix;
|
||||
FUnits := TList.Create;
|
||||
FDefaultUnitExtension:='.pas';
|
||||
FOptions:=AOptions;
|
||||
FUnitPrefix:=AUnitPrefix;
|
||||
end;
|
||||
|
||||
procedure TgirPascalWriter.GenerateUnits;
|
||||
var
|
||||
i: Integer;
|
||||
UnitGroup: TPascalUnitGroup;
|
||||
|
||||
|
||||
begin
|
||||
for i := 0 to FNameSpaces.Count-1 do
|
||||
begin
|
||||
WriteLn(Format('Converting %s', [FNameSpaces.NameSpace[i].NameSpace]));
|
||||
UnitGroup := TPascalUnitGroup.Create(Self, FNameSpaces.NameSpace[i], FOptions, FUnitPrefix);
|
||||
UnitGroup.GenerateUnits;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
2543
tools/gir2pascal/girpascalwritertypes.pas
Normal file
2543
tools/gir2pascal/girpascalwritertypes.pas
Normal file
File diff suppressed because it is too large
Load Diff
186
tools/gir2pascal/girtokens.pas
Normal file
186
tools/gir2pascal/girtokens.pas
Normal file
@ -0,0 +1,186 @@
|
||||
{
|
||||
girtokens.pas
|
||||
Copyright (C) 2011 Andrew Haines andrewd207@aol.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
}
|
||||
unit girTokens;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes;
|
||||
|
||||
type
|
||||
TGirToken = (gtInvalid, gtEmpty, gtAlias, gtConstant, gtRecord, gtBitField, gtEnumeration,
|
||||
gtCallback, gtUnion, gtFunction, gtReturnValue, gtType,
|
||||
gtParameters, gtParameter, gtInstanceParameter, gtMember, gtField, gtMethod, gtArray,
|
||||
gtDoc, gtDocDeprecated, gtConstructor, gtRepository, gtInclude, gtNameSpace, gtPackage,
|
||||
gtCInclude, gtClass, gtProperty, gtVirtualMethod, gtInterface,
|
||||
gtGlibSignal, gtImplements, gtPrerequisite,gtVarArgs, gtObject, gtClassStruct, gtGType,
|
||||
// Direction for parameters. in is default = no pointer. out and inout means one pointer level.
|
||||
// If subnode is array then increase pointer level.
|
||||
gtIn, gtOut, gtInOut, gtSourcePosition
|
||||
);
|
||||
|
||||
TGirVersion = object
|
||||
Major: Integer;
|
||||
Minor: Integer;
|
||||
function AsString: String; // '$major.$minor'
|
||||
function AsMajor: TGirVersion; // return as $major.0 i.e 3.0 instead of 3.8
|
||||
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
GirTokenName: array[TGirToken] of String = (
|
||||
'Invalid Name',
|
||||
'{empty}',
|
||||
'alias',
|
||||
'constant',
|
||||
'record',
|
||||
'bitfield',
|
||||
'enumeration',
|
||||
'callback',
|
||||
'union',
|
||||
'function',
|
||||
'return-value',
|
||||
'type',
|
||||
'parameters',
|
||||
'parameter',
|
||||
'instance-parameter',
|
||||
'member',
|
||||
'field',
|
||||
'method',
|
||||
'array',
|
||||
'doc',
|
||||
'doc-deprecated',
|
||||
'constructor',
|
||||
'repository',
|
||||
'include',
|
||||
'namespace',
|
||||
'package',
|
||||
'c:include',
|
||||
'class',
|
||||
'property',
|
||||
'virtual-method',
|
||||
'interface',
|
||||
'glib:signal',
|
||||
'implements',
|
||||
'prerequisite',
|
||||
'varargs',
|
||||
'object',
|
||||
'classstruct',
|
||||
'gtype',
|
||||
'in',
|
||||
'out',
|
||||
'inout',
|
||||
'source-position'
|
||||
);
|
||||
|
||||
function GirTokenNameToToken(AName: String): TGirToken;
|
||||
function girVersion(AVersion: String; ADefaultMajor: Integer = -1; ADefaultMinor: Integer = -1): TGirVersion;
|
||||
function girVersion(AMajor, AMinor: Integer): TGirVersion;
|
||||
|
||||
operator >= (AVersion, BVersion: TGirVersion): Boolean;
|
||||
operator <= (AVersion, BVersion: TGirVersion): Boolean;
|
||||
operator > (AVersion, BVersion: TGirVersion): Boolean;
|
||||
|
||||
implementation
|
||||
uses
|
||||
sysutils;
|
||||
|
||||
function GirTokenNameToToken(AName: String): TGirToken;
|
||||
begin
|
||||
if AName = '' then
|
||||
Exit(gtEmpty);
|
||||
try
|
||||
for Result in TGirToken do
|
||||
if GirTokenName[Result][1] <> AName[1] then
|
||||
continue
|
||||
else if GirTokenName[Result] = AName then
|
||||
Exit;
|
||||
Result := gtInvalid;
|
||||
|
||||
except
|
||||
WriteLn('GirToken Exception: ',AName);
|
||||
end;
|
||||
end;
|
||||
|
||||
function girVersion(AVersion: String; ADefaultMajor: Integer; ADefaultMinor: Integer): TGirVersion;
|
||||
var
|
||||
SplitPoint: Integer;
|
||||
Minor: String;
|
||||
begin
|
||||
if (AVersion = '') and (ADefaultMajor <> -1) and (ADefaultMinor <> -1) then
|
||||
begin
|
||||
Result := girVersion(ADefaultMajor, ADefaultMinor);
|
||||
Exit;
|
||||
end;
|
||||
SplitPoint := Pos('.', AVersion);
|
||||
|
||||
if SplitPoint < 1 then
|
||||
raise Exception.Create(Format('Invalid version string format: "%s" (length %d)', [AVersion, Length(AVersion)]));
|
||||
|
||||
Result.Major:=StrToInt(Copy(AVersion,1, SplitPoint-1));
|
||||
Minor := Copy(AVersion,SplitPoint+1, MaxInt);
|
||||
SplitPoint := Pos('.', Minor);
|
||||
// we are not interested in the third version chunk
|
||||
if SplitPoint > 0 then
|
||||
Minor := Copy(Minor,1, SplitPoint-1);
|
||||
Result.Minor:=StrToInt(Minor);
|
||||
end;
|
||||
|
||||
function girVersion(AMajor, AMinor: Integer): TGirVersion;
|
||||
begin
|
||||
REsult.Major := AMajor;
|
||||
Result.Minor := AMinor;
|
||||
end;
|
||||
|
||||
operator >= (AVersion, BVersion: TGirVersion): Boolean;
|
||||
begin
|
||||
Result := (AVersion.Major > BVersion.Major)
|
||||
or ((AVersion.Major = BVersion.Major) and (AVersion.Minor >= BVersion.Minor));
|
||||
end;
|
||||
|
||||
operator<=(AVersion, BVersion: TGirVersion): Boolean;
|
||||
begin
|
||||
Result := (AVersion.Major < BVersion.Major)
|
||||
or ((AVersion.Major = BVersion.Major) and (AVersion.Minor <= BVersion.Minor));
|
||||
end;
|
||||
|
||||
operator > (AVersion, BVersion: TGirVersion): Boolean;
|
||||
begin
|
||||
Result := (AVersion.Major > BVersion.Major)
|
||||
or ((AVersion.Major = BVersion.Major) and (AVersion.Minor > BVersion.Minor));
|
||||
end;
|
||||
|
||||
{ TGirVersion }
|
||||
|
||||
function TGirVersion.AsString: String;
|
||||
begin
|
||||
Result := IntToStr(Major)+'.'+IntToStr(Minor);
|
||||
end;
|
||||
|
||||
function TGirVersion.AsMajor: TGirVersion;
|
||||
begin
|
||||
Result.Major:=Major;
|
||||
REsult.Minor:=0;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user