* JSON2pas command-line tool added

git-svn-id: trunk@35297 -
This commit is contained in:
michael 2017-01-14 10:22:16 +00:00
parent e6000e88d1
commit 180b93b326
8 changed files with 2974 additions and 0 deletions

5
.gitattributes vendored
View File

@ -16396,6 +16396,11 @@ utils/javapp/src/fpc/tools/javapp/StackMapTableData.java svneol=native#text/plai
utils/javapp/src/fpc/tools/javapp/Tables.java svneol=native#text/plain
utils/javapp/src/fpc/tools/javapp/TrapData.java svneol=native#text/plain
utils/javapp/src/fpc/tools/javapp/TypeSignature.java svneol=native#text/plain
utils/json2pas/Makefile svneol=native#text/plain
utils/json2pas/Makefile.fpc svneol=native#text/plain
utils/json2pas/fpmake.pp svneol=native#text/plain
utils/json2pas/json2pas.lpi svneol=native#text/plain
utils/json2pas/json2pas.pp svneol=native#text/plain
utils/mkinsadd.pp svneol=native#text/plain
utils/mksymbian/Makefile svneol=native#text/plain
utils/mksymbian/Makefile.fpc svneol=native#text/plain

View File

@ -8,6 +8,7 @@
add_fppkg_util(ADirectory+IncludeTrailingPathDelimiter('fppkg'));
add_fprcp(ADirectory+IncludeTrailingPathDelimiter('fprcp'));
add_h2pas(ADirectory+IncludeTrailingPathDelimiter('h2pas'));
add_json2pas(ADirectory+IncludeTrailingPathDelimiter('json2pas'));
add_importtl(ADirectory+IncludeTrailingPathDelimiter('importtl'));
add_instantfpc(ADirectory+IncludeTrailingPathDelimiter('instantfpc'));
add_pas2fpm(ADirectory+IncludeTrailingPathDelimiter('pas2fpm'));

View File

@ -18,6 +18,8 @@
{$include h2pas/fpmake.pp}
{$include json2pas/fpmake.pp}
{$include importtl/fpmake.pp}
{$include instantfpc/fpmake.pp}

2607
utils/json2pas/Makefile Normal file

File diff suppressed because it is too large Load Diff

102
utils/json2pas/Makefile.fpc Normal file
View File

@ -0,0 +1,102 @@
#
# Makefile.fpc for running fpmake
#
[package]
name=json2pas
version=3.1.1
[require]
packages=rtl fpmkunit fcl-json
[install]
fpcpackage=y
[default]
fpcdir=../..
[prerules]
FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
ifdef OS_TARGET
FPC_TARGETOPT+=--os=$(OS_TARGET)
endif
ifdef CPU_TARGET
FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
endif
LOCALFPMAKE=./fpmake$(SRCEXEEXT)
[rules]
# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own.
override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm
override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
# Compose general fpmake-parameters
ifdef FPMAKEOPT
FPMAKE_OPT+=$(FPMAKEOPT)
endif
FPMAKE_OPT+=--localunitdir=../..
FPMAKE_OPT+=--globalunitdir=../../packages
FPMAKE_OPT+=$(FPC_TARGETOPT)
FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
FPMAKE_OPT+=--compiler=$(FPC)
FPMAKE_OPT+=-bu
.NOTPARALLEL:
fpmake$(SRCEXEEXT): fpmake.pp
$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
all: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT)
smart: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
release: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
debug: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
# most often fail because the dependencies are cleared.
# In case of a clean, simply do nothing
ifeq ($(FPMAKE_BIN_CLEAN),)
clean:
else
clean:
$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
endif
# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
# when the package is compiled using fpcmake prior to running this clean using fpmake
ifeq ($(FPMAKE_BIN_CLEAN),)
distclean: $(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
else
distclean:
ifdef inUnix
{ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi; }
else
$(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
endif
-$(DEL) $(LOCALFPMAKE)
endif
cleanall: distclean
install: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
else
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
endif
# distinstall also installs the example-sources and omits the location of the source-
# files from the fpunits.cfg files.
distinstall: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
else
$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
endif
zipinstall: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
zipdistinstall: fpmake$(SRCEXEEXT)
$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
zipsourceinstall: fpmake$(SRCEXEEXT)
ifdef UNIXHier
$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
else
$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
endif

45
utils/json2pas/fpmake.pp Normal file
View File

@ -0,0 +1,45 @@
{$ifndef ALLPACKAGES}
{$mode objfpc}{$H+}
program fpmake;
uses fpmkunit;
{$endif ALLPACKAGES}
procedure add_json2pas(const ADirectory: string);
Var
P : TPackage;
T : TTarget;
begin
With Installer do
begin
P:=AddPackage('utils-json2pas');
P.Dependencies.Add('fcl-json');
P.ShortName:='json2pas';
P.Author := 'Michael Van Canneyt';
P.License := 'LGPL with modification';
P.HomepageURL := 'www.freepascal.org';
P.Email := '';
P.Description := 'A utility to create Object Pascal classes files from sample JSON files.';
P.NeedLibC:= false;
P.Directory:=ADirectory;
P.Version:='3.1.1';
T:=P.Targets.AddProgram('json2pas.pp');
end;
end;
{$ifndef ALLPACKAGES}
begin
add_json2pas('');
Installer.Run;
end.
{$endif ALLPACKAGES}

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="JSON to Pascal code generator"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<Units Count="1">
<Unit0>
<Filename Value="json2pas.pp"/>
<IsPartOfProject Value="True"/>
</Unit0>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="json2pas"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

153
utils/json2pas/json2pas.pp Normal file
View File

@ -0,0 +1,153 @@
{ JSON 2 Pascal class converter
Copyright (C) 2016 Michael Van Canneyt (michael@freepascal.org)
This source 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 code 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.
A copy of the GNU General Public License is available on the World Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can
also obtain it by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
program json2pas;
{$mode objfpc}{$H+}
uses
Classes, SysUtils, CustApp, jsonparser, fpjsontopas;
type
{ TJSON2PasApplication }
TJSON2PasApplication = class(TCustomApplication)
Private
FGen : TJSONToPascal;
FIN : TFileStream;
FON : String;
procedure ProcessOptions;
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure Usage(Msg: String); virtual;
end;
{ TJSON2PasApplication }
procedure TJSON2PasApplication.ProcessOptions;
var
UN,J: String;
begin
UN:='';
if HasOption('d','generate-delphi') then
FGen.Options:=FGen.Options+[jpoDelphiJSON];
if HasOption('l','generate-load') then
FGen.Options:=FGen.Options+[jpoGenerateLoad];
if HasOption('s','generate-save') then
FGen.Options:=FGen.Options+[jpoGenerateSave];
if HasOption('c','load-ignores-case') then
FGen.Options:=FGen.Options+[jpoLoadCaseInsensitive];
if HasOption('e','use-setter') then
FGen.Options:=FGen.Options+[jpoUseSetter];
if HasOption('r','load-with-error') then
FGen.Options:=FGen.Options+[jpoUnknownLoadPropsError];
if HasOption('u','unit') then
UN:=GetOptionValue('u','unit');
J:=GetOptionValue('i','input');
if (J<>'') then
begin
FIN:=TFileStream.Create(J,fmOpenRead or fmShareDenyWrite);
FGen.JSONStream:=FIN;
end
else
FGen.JSON:=getOptionValue('j','json');
if HasOption('o','output') then
FON:=GetOptionValue('o','output');
if (FON='') then
begin
if Assigned(FIN) then
FON:=ChangeFileExt(FIN.FileName,'')
else if (UN<>'') then
FON:=UN;
if (UN='') then
UN:=ChangeFileExt(ExtractFileName(FON),'');
end
else
UN:=ChangeFileExt(ExtractFileName(FON),'');
if (ExtractFileExt(FON)='') then
if (jpoDelphiJSON in Fgen.Options) then
FON:=FON+'.pas'
else
FON:=FON+'.pp';
FGen.DestUnitName:=UN;
If HasOption('n','classname') then
FGen.PropertyMap.AddPath('',GetOptionValue('n','classname'));
end;
procedure TJSON2PasApplication.DoRun;
var
ErrorMsg: String;
begin
// quick check parameters
ErrorMsg:=CheckOptions('hi:j:u:o:n:dlscer', ['help','input:','output:','unit:','json:','generate-delphi','generate-load','generate-save','load-ignores-case','use-setter','classname:','load-with-error']);
if (ErrorMsg<>'') or HasOption('h', 'help') then
Usage(ErrorMsg);
ProcessOptions;
FGen.Execute;
FGen.Code.SaveToFile(FON);
Terminate;
end;
constructor TJSON2PasApplication.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
StopOnException:=True;
FGen:=TJSONToPascal.Create(Self);
end;
destructor TJSON2PasApplication.Destroy;
begin
FreeAndNil(FGen);
FreeAndNil(FIN);
inherited Destroy;
end;
procedure TJSON2PasApplication.Usage(Msg : String);
begin
if (Msg<>'') then
Writeln('Error : ',Msg);
writeln('Usage: ', ExeName, ' [options]');
Writeln('Where options is one or more of:');
// 'hi:j:u:o:n:dlscer', ['help','input:','output:','unit:','json:','generate-delphi','generate-load','generate-save','load-ignores-case','use-setter','classname:','load-with-error']);
Writeln('-h --help Show this help');
Writeln('-i --input=file Use file as JSON input. The file must contain a valid JSON object.');
Writeln('-i --json=json Use json as JSON input. The value must contain a valid JSON object.');
Writeln('-u --unit=name Use name as the name of the unit.');
Writeln(' If no output file is specified, this sets the name');
Writeln('-o --output=file Set the output filename. Sets the unit name if none is given');
Writeln('-d --generate-delphi Use Delphi 10 JSON routines');
Writeln('-l --generate-load Create LoadFromJSON routine');
Writeln('-s --generate-save Create SaveToJSON routine');
Writeln('-c --load-ignores-case The LoadFromJSON routine will ignore case');
Writeln('-e --use-setter Property setters use a routine instead of writing to field');
Writeln('-n --classname=name Set the name of the top-level class (default: TMyObject)');
Writeln('-r --load-with-error Load will raise an exception if an unknown property is met');
Halt(Ord(Msg<>''));
end;
var
Application: TJSON2PasApplication;
begin
Application:=TJSON2PasApplication.Create(nil);
Application.Title:='JSON to Pascal code generator';
Application.Run;
Application.Free;
end.