@ -0,0 +1,10 @@
|
|||||||
|
FROM debian:bookworm as builder
|
||||||
|
|
||||||
|
COPY bin/dockerproxy-main /bin/dockerproxy-main
|
||||||
|
|
||||||
|
COPY docker/entrypoint.sh /
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
USER root
|
||||||
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT [ "/entrypoint.sh" ]
|
@ -0,0 +1,38 @@
|
|||||||
|
FROM debian:bookworm as builder
|
||||||
|
|
||||||
|
RUN apt -y update && apt -y install unzip git curl gnat
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/local/src/alr
|
||||||
|
ADD https://github.com/alire-project/alire/releases/download/v1.2.2/alr-1.2.2-bin-x86_64-linux.zip /usr/local/src/alr/alr.zip
|
||||||
|
RUN cd /usr/local/src/alr && unzip alr.zip && rm -f alr.zip
|
||||||
|
|
||||||
|
ENV PATH="$PATH:/usr/local/src/alr/bin"
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN mkdir -p /root/.config/alire
|
||||||
|
|
||||||
|
RUN alr -d get --build gnat_native
|
||||||
|
RUN alr -d get --build gprbuild
|
||||||
|
|
||||||
|
RUN alr toolchain
|
||||||
|
|
||||||
|
COPY docker/config.toml /root/.config/alire/
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/local/src/codefirst-dockerproxy
|
||||||
|
WORKDIR /usr/local/src/codefirst-dockerproxy
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN ls -la
|
||||||
|
|
||||||
|
RUN alr -d build
|
||||||
|
|
||||||
|
# FROM debian:bookwork
|
||||||
|
|
||||||
|
# COPY --from=builder /usr/local/codefirst-dockerproxy/greet /bin/greet
|
||||||
|
|
||||||
|
# COPY docker/entrypoint.sh /
|
||||||
|
# RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
# USER root
|
||||||
|
# EXPOSE 8080
|
||||||
|
# ENTRYPOINT [ "/entrypoint.sh" ]
|
@ -0,0 +1,11 @@
|
|||||||
|
name = "codefirst_dockerproxy"
|
||||||
|
description = "Shiny new project"
|
||||||
|
version = "0.1.0-dev"
|
||||||
|
|
||||||
|
authors = ["Thomas Bellembois"]
|
||||||
|
maintainers = ["Thomas Bellembois <thomas.bellembois@uca.fr>"]
|
||||||
|
maintainers-logins = ["tbellembois"]
|
||||||
|
|
||||||
|
executables = ["codefirst_dockerproxy"]
|
||||||
|
[[depends-on]]
|
||||||
|
aws = "^23.0.0"
|
@ -0,0 +1,30 @@
|
|||||||
|
with "config/codefirst_dockerproxy_config.gpr";
|
||||||
|
with "lib/ada-tokenizer/tokenizer.gpr";
|
||||||
|
with "lib/gclp/gclp.gpr";
|
||||||
|
|
||||||
|
project Codefirst_Dockerproxy is
|
||||||
|
|
||||||
|
for Source_Dirs use ("src", "config");
|
||||||
|
for Object_Dir use "obj/" & Codefirst_Dockerproxy_Config.Build_Profile;
|
||||||
|
for Create_Missing_Dirs use "True";
|
||||||
|
for Exec_Dir use "bin";
|
||||||
|
for Main use ("dockerproxy-main.adb");
|
||||||
|
|
||||||
|
package Compiler is
|
||||||
|
for Default_Switches ("ada") use ("-ffunction-sections", "-fdata-sections", "-g", "-gnat2020", "-O2", "-gnatVa", "-gnatwa.X", "-gnatyaABbc-defhiIklM79nOprStux");
|
||||||
|
end Compiler;
|
||||||
|
|
||||||
|
package Binder is
|
||||||
|
for Switches ("Ada") use ("-Es"); -- Symbolic traceback
|
||||||
|
end Binder;
|
||||||
|
|
||||||
|
package Install is
|
||||||
|
for Artifacts (".") use ("share");
|
||||||
|
end Install;
|
||||||
|
|
||||||
|
package Builder is
|
||||||
|
for Switches ("ada") use ("-j4");
|
||||||
|
end Builder;
|
||||||
|
|
||||||
|
end Codefirst_Dockerproxy;
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
-- Configuration for codefirst_dockerproxy generated by Alire
|
||||||
|
pragma Restrictions (No_Elaboration_Code);
|
||||||
|
pragma Style_Checks (Off);
|
||||||
|
|
||||||
|
package Codefirst_Dockerproxy_Config is
|
||||||
|
pragma Pure;
|
||||||
|
|
||||||
|
Crate_Version : constant String := "0.1.0-dev";
|
||||||
|
Crate_Name : constant String := "codefirst_dockerproxy";
|
||||||
|
|
||||||
|
Alire_Host_OS : constant String := "linux";
|
||||||
|
|
||||||
|
Alire_Host_Arch : constant String := "x86_64";
|
||||||
|
|
||||||
|
Alire_Host_Distro : constant String := "ubuntu";
|
||||||
|
|
||||||
|
type Build_Profile_Kind is (release, validation, development);
|
||||||
|
Build_Profile : constant Build_Profile_Kind := development;
|
||||||
|
|
||||||
|
end Codefirst_Dockerproxy_Config;
|
@ -0,0 +1,50 @@
|
|||||||
|
-- Configuration for codefirst_dockerproxy generated by Alire
|
||||||
|
with "aws.gpr";
|
||||||
|
abstract project Codefirst_Dockerproxy_Config is
|
||||||
|
Crate_Version := "0.1.0-dev";
|
||||||
|
Crate_Name := "codefirst_dockerproxy";
|
||||||
|
|
||||||
|
Alire_Host_OS := "linux";
|
||||||
|
|
||||||
|
Alire_Host_Arch := "x86_64";
|
||||||
|
|
||||||
|
Alire_Host_Distro := "ubuntu";
|
||||||
|
Ada_Compiler_Switches := External_As_List ("ADAFLAGS", " ");
|
||||||
|
Ada_Compiler_Switches := Ada_Compiler_Switches &
|
||||||
|
(
|
||||||
|
"-Og" -- Optimize for debug
|
||||||
|
,"-ffunction-sections" -- Separate ELF section for each function
|
||||||
|
,"-fdata-sections" -- Separate ELF section for each variable
|
||||||
|
,"-g" -- Generate debug info
|
||||||
|
,"-gnatwa" -- Enable all warnings
|
||||||
|
,"-gnatw.X" -- Disable warnings for No_Exception_Propagation
|
||||||
|
,"-gnatVa" -- All validity checks
|
||||||
|
,"-gnaty3" -- Specify indentation level of 3
|
||||||
|
,"-gnatya" -- Check attribute casing
|
||||||
|
,"-gnatyA" -- Use of array index numbers in array attributes
|
||||||
|
,"-gnatyB" -- Check Boolean operators
|
||||||
|
,"-gnatyb" -- Blanks not allowed at statement end
|
||||||
|
,"-gnatyc" -- Check comments
|
||||||
|
,"-gnaty-d" -- Disable check no DOS line terminators present
|
||||||
|
,"-gnatye" -- Check end/exit labels
|
||||||
|
,"-gnatyf" -- No form feeds or vertical tabs
|
||||||
|
,"-gnatyh" -- No horizontal tabs
|
||||||
|
,"-gnatyi" -- Check if-then layout
|
||||||
|
,"-gnatyI" -- check mode IN keywords
|
||||||
|
,"-gnatyk" -- Check keyword casing
|
||||||
|
,"-gnatyl" -- Check layout
|
||||||
|
,"-gnatym" -- Check maximum line length
|
||||||
|
,"-gnatyn" -- Check casing of entities in Standard
|
||||||
|
,"-gnatyO" -- Check that overriding subprograms are explicitly marked as such
|
||||||
|
,"-gnatyp" -- Check pragma casing
|
||||||
|
,"-gnatyr" -- Check identifier references casing
|
||||||
|
,"-gnatyS" -- Check no statements after THEN/ELSE
|
||||||
|
,"-gnatyt" -- Check token spacing
|
||||||
|
,"-gnatyu" -- Check unnecessary blank lines
|
||||||
|
,"-gnatyx" -- Check extra parentheses
|
||||||
|
);
|
||||||
|
|
||||||
|
type Build_Profile_Kind is ("release", "validation", "development");
|
||||||
|
Build_Profile : Build_Profile_Kind := "development";
|
||||||
|
|
||||||
|
end Codefirst_Dockerproxy_Config;
|
@ -0,0 +1,20 @@
|
|||||||
|
/* Configuration for codefirst_dockerproxy generated by Alire */
|
||||||
|
#ifndef CODEFIRST_DOCKERPROXY_CONFIG_H
|
||||||
|
#define CODEFIRST_DOCKERPROXY_CONFIG_H
|
||||||
|
|
||||||
|
#define CRATE_VERSION "0.1.0-dev"
|
||||||
|
#define CRATE_NAME "codefirst_dockerproxy"
|
||||||
|
|
||||||
|
#define ALIRE_HOST_OS "linux"
|
||||||
|
|
||||||
|
#define ALIRE_HOST_ARCH "x86_64"
|
||||||
|
|
||||||
|
#define ALIRE_HOST_DISTRO "ubuntu"
|
||||||
|
|
||||||
|
#define BUILD_PROFILE_RELEASE 1
|
||||||
|
#define BUILD_PROFILE_VALIDATION 2
|
||||||
|
#define BUILD_PROFILE_DEVELOPMENT 3
|
||||||
|
|
||||||
|
#define BUILD_PROFILE 3
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,13 @@
|
|||||||
|
[toolchain]
|
||||||
|
assistant = false
|
||||||
|
[toolchain.external]
|
||||||
|
gnat = "FALSE"
|
||||||
|
gprbuild = "FALSE"
|
||||||
|
[toolchain.use]
|
||||||
|
gnat = "gnat_native=12.2.1"
|
||||||
|
gprbuild = "gprbuild=22.0.0"
|
||||||
|
[user]
|
||||||
|
email = "thomas.bellembois@uca.fr"
|
||||||
|
github_login = "tbellembois"
|
||||||
|
name = "Thomas Bellembois"
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
HostName=""
|
||||||
|
DockerNetworkName=""
|
||||||
|
DockerPathPrefix=""
|
||||||
|
Scheme=""
|
||||||
|
MaxAllowedContainers=""
|
||||||
|
Admins=""
|
||||||
|
Devel=""
|
||||||
|
|
||||||
|
if [ ! -z "$DEVEL" ]
|
||||||
|
then
|
||||||
|
Devel="--devel=$DEVEL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$HOSTNAME" ]
|
||||||
|
then
|
||||||
|
HostName="--hostname=$HOSTNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$SCHEME" ]
|
||||||
|
then
|
||||||
|
Scheme="--scheme=$SCHEME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$ADMINS" ]
|
||||||
|
then
|
||||||
|
Admins="--admins=$ADMINS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$DOCKERNETWORKNAME" ]
|
||||||
|
then
|
||||||
|
DockerNetworkName="--dockernetworkname=$DOCKERNETWORKNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$DOCKERPATHPREFIX" ]
|
||||||
|
then
|
||||||
|
DockerPathPrefix="--dockerpathprefix=$DOCKERPATHPREFIX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$MAXALLOWEDCONTAINERS" ]
|
||||||
|
then
|
||||||
|
MaxAllowedContainers="--maxallowedcontainers=$MAXALLOWEDCONTAINERS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $Scheme
|
||||||
|
echo $HostName
|
||||||
|
echo $DockerNetworkName
|
||||||
|
echo $DockerPathPrefix
|
||||||
|
echo $MaxAllowedContainers
|
||||||
|
echo $Admins
|
||||||
|
|
||||||
|
/bin/dockerproxy-main $Devel $Scheme $HostName $DockerNetworkName $DockerPathPrefix $MaxAllowedContainers $Admins
|
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c0714d9103b17429568a68d51bd273950bdce21a
|
@ -0,0 +1,2 @@
|
|||||||
|
1.0.0 2012-12-14
|
||||||
|
* First public release
|
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 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.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
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.
|
@ -0,0 +1,44 @@
|
|||||||
|
** Index **
|
||||||
|
|
||||||
|
[1] What is this
|
||||||
|
[2] How do I install & use it?
|
||||||
|
[3] Where can I find more documentation?
|
||||||
|
|
||||||
|
** [1] What is this? **
|
||||||
|
|
||||||
|
This is a small generic package for parsing command line parameters. Yes, I know there are tons of libraries like this around the world, but I find this quite convenient to use.
|
||||||
|
|
||||||
|
** [2] How do I install & use it? **
|
||||||
|
|
||||||
|
== To install it:
|
||||||
|
Just copy the two files (generic_line_parser.{ads,adb}) in a place where your Ada compiler will find them. If you use GNAT/GPS, you could want to copy the project file gclp.gpr (that you will "with" from your project file)
|
||||||
|
|
||||||
|
== To use it:
|
||||||
|
The main characteristics of this package are
|
||||||
|
|
||||||
|
(1) Parameters are *nominal*, not *positional*. I wrote this package one day I needed to pass a lot of parameters to a program. In that case the positional convention was too "fragile," so I decided to go for the nominal convention. More precisely, the parameters have the form
|
||||||
|
|
||||||
|
<name>=<value>
|
||||||
|
|
||||||
|
where <name> is any string without "=" or "," and <value> is any string. The value part can also be omitted to obtain parameters of type
|
||||||
|
|
||||||
|
<name>
|
||||||
|
|
||||||
|
For example, a program (say, foo) using this package could accept a command line like
|
||||||
|
|
||||||
|
foo input=from.txt output=to.txt lines=12 fast-compile
|
||||||
|
|
||||||
|
Note that since parameters are nominal, the following line is usually equivalent to the line above
|
||||||
|
|
||||||
|
foo lines=12 input=from.txt fast-compile output=to.txt
|
||||||
|
|
||||||
|
(but order-dependent processing is still possible).
|
||||||
|
|
||||||
|
(2) The parameter values are written inside a variable whose type is passed as formal parameter to the package at instantiation time. The variable is written by using some "callbacks" provided by the user of the package. Note with this solution, the variable can be of any type, although the usually it will be a record.
|
||||||
|
|
||||||
|
** [3] Where can I find more information? **
|
||||||
|
|
||||||
|
(1) You should find a directory doc/ with documentation in HTML format
|
||||||
|
(2) In the directory test/ you can find an example of usage
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
20230124145449
|
||||||
|
-c
|
||||||
|
-x
|
||||||
|
ada
|
||||||
|
-gnatA
|
||||||
|
-gnata
|
||||||
|
-g
|
@ -0,0 +1,177 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Package: Generic_Line_Parser (generic)
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<link rel='stylesheet' href='support/tags.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<a href='index.html'><div class="button2">Table of Contents</div></a>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id='navigation'>
|
||||||
|
<h2 class="button">Navigation</h2>
|
||||||
|
<a href='#Description'><div class="button2">Description</div></a>
|
||||||
|
<a href='#Types'><div class="button2">Types</div></a>
|
||||||
|
<a href='#Constants'><div class="button2">Constants & Global variables</div></a>
|
||||||
|
<a href='#Methods'><div class="button2">Subprograms & Entries</div></a>
|
||||||
|
</div><!-- navigation -->
|
||||||
|
</div>
|
||||||
|
</div> <!-- leftSide -->
|
||||||
|
|
||||||
|
<div class='default' id='rightSide'>
|
||||||
|
<div id='rightSideInside'>
|
||||||
|
<div id='Index'>
|
||||||
|
<h2>Index</h2>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var names = new Array (
|
||||||
|
new Array ('Parameter_<wbr/>Callback', 'generic_line_parser.ads:60:9', 'type-spec'),
|
||||||
|
new Array ('Parameter_<wbr/>Descriptor', 'generic_line_parser.ads:65:9', 'type-spec'),
|
||||||
|
new Array ('Parameter_<wbr/>Descriptor_<wbr/>Array', 'generic_line_parser.ads:85:9', 'type-spec'),
|
||||||
|
new Array ('Bad_<wbr/>Command', 'generic_line_parser.ads:98:4', 'var-spec'),
|
||||||
|
new Array ('Parse_<wbr/>Command_<wbr/>Line', 'generic_line_parser.ads:92:14', 'subp-spec'),
|
||||||
|
new Array ('To_<wbr/>Float', 'generic_line_parser.ads:103:13', 'subp-spec'),
|
||||||
|
new Array ('To_<wbr/>Natural', 'generic_line_parser.ads:108:13', 'subp-spec'),
|
||||||
|
new Array ('dummy', '', ''));
|
||||||
|
printIndexList (names);
|
||||||
|
</script>
|
||||||
|
<noscript>
|
||||||
|
<ul>
|
||||||
|
<li class='type-spec'><a href="#generic_line_parser.ads:60:9">Parameter_<wbr/>Callback</a></li>
|
||||||
|
<li class='type-spec'><a href="#generic_line_parser.ads:65:9">Parameter_<wbr/>Descriptor</a></li>
|
||||||
|
<li class='type-spec'><a href="#generic_line_parser.ads:85:9">Parameter_<wbr/>Descriptor_<wbr/>Array</a></li>
|
||||||
|
<li class='var-spec'><a href="#generic_line_parser.ads:98:4">Bad_<wbr/>Command</a></li>
|
||||||
|
<li class='subp-spec'><a href="#generic_line_parser.ads:92:14">Parse_<wbr/>Command_<wbr/>Line</a></li>
|
||||||
|
<li class='subp-spec'><a href="#generic_line_parser.ads:103:13">To_<wbr/>Float</a></li>
|
||||||
|
<li class='subp-spec'><a href="#generic_line_parser.ads:108:13">To_<wbr/>Natural</a></li>
|
||||||
|
</ul>
|
||||||
|
</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='default' id='documentation'>
|
||||||
|
<div class='title'>
|
||||||
|
Package: <i>Generic_Line_Parser (generic)</i>
|
||||||
|
(<a href="src_generic_line_parser.ads.html">Source File</a>)
|
||||||
|
</div>
|
||||||
|
<div class='subprograms'>
|
||||||
|
<h1><a name='Description' id='Description'></a>Description</h1>
|
||||||
|
<div class="class">
|
||||||
|
<div class='details'><pre><span class="keyword">generic</span>
|
||||||
|
<span class="keyword">type</span> <span class="name"><a name="generic_line_parser.ads:49:9"></a>Config_Data</span> <span class="keyword">is</span> <span class="keyword">limited</span> <span class="keyword">private</span>;
|
||||||
|
<span class="comment">-- The parameters read from the command line will be written in
|
||||||
|
</span> <span class="comment">-- a variable of this type
|
||||||
|
</span>
|
||||||
|
<span class="comment">-- Set this to False if you want case insensitive option matching.
|
||||||
|
</span> <span class="comment">-- For example, if you set this to False, "input", "Input", "INPUT"
|
||||||
|
</span> <span class="comment">-- and "InPuT" will be equivalent names for the option "input"
|
||||||
|
</span> <span class="name"><a name="generic_line_parser.ads:56:4"></a>Case_Sensitive</span> : Boolean := True;
|
||||||
|
<span class="keyword">package</span> <span class="name"><b>Generic_Line_Parser</b></span> <span class="keyword">is</span></pre></div>
|
||||||
|
<div class='comment'><div class="summary" ><p>This is a generic package implementing a simple-to-use command line parser. Yes, I know, everyone makes his/her own command line parser... so, I wrote mine. As they say, every open source project starts with a programmer that schratches hes own itch. So I did... If you find this useful, you are welcome to use it. </p><p>The ideas behind this package are the following </p><p>* Parameters are nominal, non positional. The syntax is of "named parameter" type, that is, each command line parameter is expected to have thefollowing format </p><p>label ['=' value] </p><p>where "label" is any string without '='. </p><p>* Parsed value are written in a "configuration variable" whose type is a formal parameter of this package. The values are written in the configuration variable by using some callbacks provided by caller. </p><p>The names of the parameters are given to the parser in "parameter description array" that is an array of records that specify </p><p>+ The parameter name </p><p>+ A default value (if needed) </p><p>+ If the parameter is mandatory </p><p>+ If it can be specified more than once </p><p>+ The callback function to be called when the parameter is found </p><p>In order to parse the command line it suffices to call Parse_Command_Line giving as argument the array of parameter descriptors and the configuration variable to be written. For every parameter found, the corresponding callback function is called. If at the end of the parsing there are some optional parameters that were missing from the command line, the corresponding callbacks are called with the default parameter.</p></div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class='subprograms'>
|
||||||
|
<h1><a name='Types' id='Types'></a>Types</h1>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:60:9' id='generic_line_parser.ads:60:9'></a>Parameter_Callback
|
||||||
|
- <a href="src_generic_line_parser.ads.html#60" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">type</span> <span class="name"><b>Parameter_Callback</b></span> <span class="keyword">is</span>
|
||||||
|
<span class="keyword">access</span> <span class="keyword">procedure</span> (Name : <span class="keyword">in</span> Unbounded_String;
|
||||||
|
Value : <span class="keyword">in</span> Unbounded_String;
|
||||||
|
Result : <span class="keyword">in</span> <span class="keyword">out</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:49:9" title="defined at generic_line_parser.ads:49:9">Config_Data</a>);</pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:65:9' id='generic_line_parser.ads:65:9'></a>Parameter_Descriptor
|
||||||
|
- <a href="src_generic_line_parser.ads.html#65" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">type</span> <span class="name"><b>Parameter_Descriptor</b></span> <span class="keyword">is</span>
|
||||||
|
<span class="keyword">record</span>
|
||||||
|
Name : Unbounded_String; <span class="comment">-- Parameter name
|
||||||
|
</span> Default : Unbounded_String; <span class="comment">-- Default value used if not on C.L.
|
||||||
|
</span> Mandatory : Boolean; <span class="comment">-- Parameter MUST be given
|
||||||
|
</span> Only_Once : Boolean; <span class="comment">-- Parameter MUST NOT be given more than once
|
||||||
|
</span> Callback : <a href="generic_line_parser.ads.html#generic_line_parser.ads:60:9" title="defined at generic_line_parser.ads:60:9">Parameter_Callback</a>; <span class="comment">-- Called when parameter found
|
||||||
|
</span> <span class="keyword">end</span> <span class="keyword">record</span>;</pre></div>
|
||||||
|
<div class='comment'><div class="description" >Record holding the description of a parameter. The fields should be self-explenatory (I hope). The only field that needs some explanation is Name since it allows to specify more than one name for each parameter. The syntax is very simple: just separate the names with commas. For example, if Name is "f,filename,input" one can use on the command line, with the same effect f=/tmp/a.txt or filename=/tmp/a.txt or input=/tmp/a.txt. Spaces at both ends of the label name are trimmed, so that, for example, "f,filename,input" is equivalent to "f , filename ,input "</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:85:9' id='generic_line_parser.ads:85:9'></a>Parameter_Descriptor_Array
|
||||||
|
- <a href="src_generic_line_parser.ads.html#85" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">type</span> <span class="name"><b>Parameter_Descriptor_Array</b></span> <span class="keyword">is</span>
|
||||||
|
<span class="keyword">array</span> (Natural <span class="keyword">range</span> <>) <span class="keyword">of</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:65:9" title="defined at generic_line_parser.ads:65:9">Parameter_Descriptor</a>;</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='subprograms'>
|
||||||
|
<h1><a name='Constants' id='Constants'></a>Constants & Global variables</h1>
|
||||||
|
<div class="class">
|
||||||
|
<h3><a name='generic_line_parser.ads:98:4' id='generic_line_parser.ads:98:4'></a>Bad_Command
|
||||||
|
- <a href="src_generic_line_parser.ads.html#98" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="name"><b>Bad_Command</b></span> : <span class="keyword">exception</span>;</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='subprograms'>
|
||||||
|
<h1><a name='Methods' id='Methods'></a>Subprograms & Entries</h1>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:92:14' id='generic_line_parser.ads:92:14'></a>Parse_Command_Line
|
||||||
|
- <a href="src_generic_line_parser.ads.html#92" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">procedure</span> <span class="name"><b>Parse_Command_Line</b></span> <table><tr><td>(</td><td><span class="name"><a name="generic_line_parser.ads:93:7"></a>Parameters</span></td><td>: <span class="keyword">in</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:85:9" title="defined at generic_line_parser.ads:85:9">Parameter_Descriptor_Array</a>;</td></tr><tr><td></td><td><span class="name"><a name="generic_line_parser.ads:94:7"></a>Result</span></td><td>: <span class="keyword">out</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:49:9" title="defined at generic_line_parser.ads:49:9">Config_Data</a>;</td></tr><tr><td></td><td><span class="name"><a name="generic_line_parser.ads:95:7"></a>Help_Line</span></td><td>: <span class="keyword">in</span> String := <span class="string">""</span>;</td></tr><tr><td></td><td><span class="name"><a name="generic_line_parser.ads:96:7"></a>Help_Output</span></td><td>: <span class="keyword">in</span> Ada.Text_IO.File_Type := Ada.Text_IO.Standard_Error);</td></tr></table></pre></div>
|
||||||
|
<div class='comment'>Main exported method. It parses the command line and it writes
|
||||||
|
the result in Result. If some error is encountered, Bad_Command
|
||||||
|
is raised with an explicative exception message. Help_Line,
|
||||||
|
if not empty, is written to Help_Output in case of error.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:103:13' id='generic_line_parser.ads:103:13'></a>To_Float
|
||||||
|
- <a href="src_generic_line_parser.ads.html#103" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">function</span> <span class="name"><b>To_Float</b></span> <table><tr><td>(</td><td><span class="name"><a name="generic_line_parser.ads:103:23"></a>X</span></td><td>: Unbounded_String)</td></tr></table><span class="keyword">return</span> Float;</pre></div>
|
||||||
|
<div class='comment'>Convenient conversion function to Float that raise Bad_Command if
|
||||||
|
the argument has not a valid syntax
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="class">
|
||||||
|
<h3>
|
||||||
|
<a name='generic_line_parser.ads:108:13' id='generic_line_parser.ads:108:13'></a>To_Natural
|
||||||
|
- <a href="src_generic_line_parser.ads.html#108" title="Goto spec">Spec</a>
|
||||||
|
</h3>
|
||||||
|
<div class='details'><pre><span class="keyword">function</span> <span class="name"><b>To_Natural</b></span> <table><tr><td>(</td><td><span class="name"><a name="generic_line_parser.ads:108:25"></a>X</span></td><td>: Unbounded_String)</td></tr></table><span class="keyword">return</span> Natural;</pre></div>
|
||||||
|
<div class='comment'>Convenient conversion function to Float that raise Bad_Command if
|
||||||
|
the argument has not a valid syntax
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- documentation -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<b>G</b>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Packages and source files (G):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:57:9" title="defined at generic_line_parser.ads:57:9">Generic_Line_Parser</a>
|
||||||
|
(<b>package</b>)
|
||||||
|
at <i>generic_line_parser.ads:57:9</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<a href="indexfG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<b>B</b>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Entities (B):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:98:4" title="defined at generic_line_parser.ads:98:4">Bad_Command</a>
|
||||||
|
(<b>constant or variable</b>)
|
||||||
|
at <i>generic_line_parser.ads:98:4</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<a href="indexfG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<b>G</b>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Entities (G):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:57:9" title="defined at generic_line_parser.ads:57:9">Generic_Line_Parser</a>
|
||||||
|
(<b>package</b>)
|
||||||
|
at <i>generic_line_parser.ads:57:9</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<a href="indexfG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<b>P</b>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Entities (P):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:60:9" title="defined at generic_line_parser.ads:60:9">Parameter_Callback</a>
|
||||||
|
(<b>type</b>)
|
||||||
|
at <i>generic_line_parser.ads:60:9</i>
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:65:9" title="defined at generic_line_parser.ads:65:9">Parameter_Descriptor</a>
|
||||||
|
(<b>type</b>)
|
||||||
|
at <i>generic_line_parser.ads:65:9</i>
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:85:9" title="defined at generic_line_parser.ads:85:9">Parameter_Descriptor_Array</a>
|
||||||
|
(<b>type</b>)
|
||||||
|
at <i>generic_line_parser.ads:85:9</i>
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:92:14" title="defined at generic_line_parser.ads:92:14">Parse_Command_Line</a>
|
||||||
|
(<b>subprogram</b>)
|
||||||
|
at <i>generic_line_parser.ads:92:14</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,66 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<a href="indexfG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<b>T</b>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Entities (T):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:103:13" title="defined at generic_line_parser.ads:103:13">To_Float</a>
|
||||||
|
(<b>subprogram</b>)
|
||||||
|
at <i>generic_line_parser.ads:103:13</i>
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:108:13" title="defined at generic_line_parser.ads:108:13">To_Natural</a>
|
||||||
|
(<b>subprogram</b>)
|
||||||
|
at <i>generic_line_parser.ads:108:13</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<b>G</b>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<a href="indexsG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Packages and source files (G):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="generic_line_parser.ads.html#generic_line_parser.ads:57:9" title="defined at generic_line_parser.ads:57:9">Generic_Line_Parser</a>
|
||||||
|
(<b>package</b>)
|
||||||
|
at <i>generic_line_parser.ads:57:9</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Table of Contents
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<i><div class="button2">Table of Contents</div></i>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBar'>
|
||||||
|
<div class='topBarInside'>
|
||||||
|
<div class='topBarLinks'>
|
||||||
|
<b>Table of Contents</b>
|
||||||
|
</div>
|
||||||
|
<div class='topBarLinks' id='fileindex'>
|
||||||
|
Packages and files Index:
|
||||||
|
[<a href="indexfG.html">G</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Entities Index:
|
||||||
|
[<a href="indexeB.html">B</a>]
|
||||||
|
[<a href="indexeG.html">G</a>]
|
||||||
|
[<a href="indexeP.html">P</a>]
|
||||||
|
[<a href="indexeT.html">T</a>]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='topBarLinks' id='entitiesindex'>
|
||||||
|
Annotated Source Files:
|
||||||
|
[<b>G</b>]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='titleTopBar'>
|
||||||
|
Annotated Source Files (G):
|
||||||
|
</div>
|
||||||
|
<div class="entity">
|
||||||
|
<a href="src_generic_line_parser.ads.html" title="generic_line_parser.ads">generic_line_parser.ads</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,143 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
File: generic_line_parser.ads
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<a href='index.html'><div class="button2">Table of Contents</div></a>
|
||||||
|
|
||||||
|
<a href='tree.html'><div class="button2">Class Inheritance Tree</div></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- leftSide -->
|
||||||
|
|
||||||
|
<div class='subprograms'>
|
||||||
|
<div class='details'><ol><li><pre><a name="1"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="2"></a> </pre></li>
|
||||||
|
<li><pre><a name="3"></a><span class="comment">-- <summary></span> </pre></li>
|
||||||
|
<li><pre><a name="4"></a><span class="comment">-- This is a generic package implementing a simple-to-use command line</span> </pre></li>
|
||||||
|
<li><pre><a name="5"></a><span class="comment">-- parser. Yes, I know, everyone makes his/her own command line parser...</span> </pre></li>
|
||||||
|
<li><pre><a name="6"></a><span class="comment">-- so, I wrote mine. As they say, every open source project starts</span> </pre></li>
|
||||||
|
<li><pre><a name="7"></a><span class="comment">-- with a programmer that schratches hes own itch. So I did... If</span> </pre></li>
|
||||||
|
<li><pre><a name="8"></a><span class="comment">-- you find this useful, you are welcome to use it.</span> </pre></li>
|
||||||
|
<li><pre><a name="9"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="10"></a><span class="comment">-- The ideas behind this package are the following</span> </pre></li>
|
||||||
|
<li><pre><a name="11"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="12"></a><span class="comment">-- * Parameters are nominal, non positional. The syntax is of</span> </pre></li>
|
||||||
|
<li><pre><a name="13"></a><span class="comment">-- "named parameter" type, that is, each command line parameter is</span> </pre></li>
|
||||||
|
<li><pre><a name="14"></a><span class="comment">-- expected to have thefollowing format</span> </pre></li>
|
||||||
|
<li><pre><a name="15"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="16"></a><span class="comment">-- label ['=' value]</span> </pre></li>
|
||||||
|
<li><pre><a name="17"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="18"></a><span class="comment">-- where "label" is any string without '='.</span> </pre></li>
|
||||||
|
<li><pre><a name="19"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="20"></a><span class="comment">-- * Parsed value are written in a "configuration variable" whose type</span> </pre></li>
|
||||||
|
<li><pre><a name="21"></a><span class="comment">-- is a formal parameter of this package. The values are written</span> </pre></li>
|
||||||
|
<li><pre><a name="22"></a><span class="comment">-- in the configuration variable by using some callbacks provided</span> </pre></li>
|
||||||
|
<li><pre><a name="23"></a><span class="comment">-- by caller.</span> </pre></li>
|
||||||
|
<li><pre><a name="24"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="25"></a><span class="comment">-- The names of the parameters are given to the parser in "parameter</span> </pre></li>
|
||||||
|
<li><pre><a name="26"></a><span class="comment">-- description array" that is an array of records that specify</span> </pre></li>
|
||||||
|
<li><pre><a name="27"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="28"></a><span class="comment">-- + The parameter name</span> </pre></li>
|
||||||
|
<li><pre><a name="29"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="30"></a><span class="comment">-- + A default value (if needed)</span> </pre></li>
|
||||||
|
<li><pre><a name="31"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="32"></a><span class="comment">-- + If the parameter is mandatory</span> </pre></li>
|
||||||
|
<li><pre><a name="33"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="34"></a><span class="comment">-- + If it can be specified more than once</span> </pre></li>
|
||||||
|
<li><pre><a name="35"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="36"></a><span class="comment">-- + The callback function to be called when the parameter is found</span> </pre></li>
|
||||||
|
<li><pre><a name="37"></a><span class="comment">--</span> </pre></li>
|
||||||
|
<li><pre><a name="38"></a><span class="comment">-- In order to parse the command line it suffices to call Parse_Command_Line</span> </pre></li>
|
||||||
|
<li><pre><a name="39"></a><span class="comment">-- giving as argument the array of parameter descriptors and the configuration</span> </pre></li>
|
||||||
|
<li><pre><a name="40"></a><span class="comment">-- variable to be written. For every parameter found, the corresponding</span> </pre></li>
|
||||||
|
<li><pre><a name="41"></a><span class="comment">-- callback function is called. If at the end of the parsing there are some</span> </pre></li>
|
||||||
|
<li><pre><a name="42"></a><span class="comment">-- optional parameters that were missing from the command line, the</span> </pre></li>
|
||||||
|
<li><pre><a name="43"></a><span class="comment">-- corresponding callbacks are called with the default parameter.</span> </pre></li>
|
||||||
|
<li><pre><a name="44"></a><span class="comment">-- </summary></span> </pre></li>
|
||||||
|
<li><pre><a name="45"></a><span class="keyword">with</span> Ada.Strings.Unbounded; </pre></li>
|
||||||
|
<li><pre><a name="46"></a><span class="keyword">with</span> Ada.Text_IO; </pre></li>
|
||||||
|
<li><pre><a name="47"></a> </pre></li>
|
||||||
|
<li><pre><a name="48"></a><span class="keyword">generic</span> </pre></li>
|
||||||
|
<li><pre><a name="49"></a> <span class="keyword">type</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:49:9" title="defined at generic_line_parser.ads:49:9">Config_Data</a> <span class="keyword">is</span> <span class="keyword">limited</span> <span class="keyword">private</span>; </pre></li>
|
||||||
|
<li><pre><a name="50"></a> <span class="comment">-- The parameters read from the command line will be written in</span> </pre></li>
|
||||||
|
<li><pre><a name="51"></a> <span class="comment">-- a variable of this type</span> </pre></li>
|
||||||
|
<li><pre><a name="52"></a> </pre></li>
|
||||||
|
<li><pre><a name="53"></a> <span class="comment">-- Set this to False if you want case insensitive option matching.</span> </pre></li>
|
||||||
|
<li><pre><a name="54"></a> <span class="comment">-- For example, if you set this to False, "input", "Input", "INPUT"</span> </pre></li>
|
||||||
|
<li><pre><a name="55"></a> <span class="comment">-- and "InPuT" will be equivalent names for the option "input"</span> </pre></li>
|
||||||
|
<li><pre><a name="56"></a> <a href="generic_line_parser.ads.html#generic_line_parser.ads:56:4" title="defined at generic_line_parser.ads:56:4">Case_Sensitive</a> : Boolean := True; </pre></li>
|
||||||
|
<li><pre><a name="57"></a><span class="keyword">package</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:57:9" title="defined at generic_line_parser.ads:57:9">Generic_Line_Parser</a> <span class="keyword">is</span> </pre></li>
|
||||||
|
<li><pre><a name="58"></a> <span class="keyword">use</span> Ada.Strings.Unbounded; </pre></li>
|
||||||
|
<li><pre><a name="59"></a> </pre></li>
|
||||||
|
<li><pre><a name="60"></a> <span class="keyword">type</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:60:9" title="defined at generic_line_parser.ads:60:9">Parameter_Callback</a> <span class="keyword">is</span> </pre></li>
|
||||||
|
<li><pre><a name="61"></a> <span class="keyword">access</span> <span class="keyword">procedure</span> (<span class="name">Name</span> : <span class="keyword">in</span> Unbounded_String; </pre></li>
|
||||||
|
<li><pre><a name="62"></a> <span class="name">Value</span> : <span class="keyword">in</span> Unbounded_String; </pre></li>
|
||||||
|
<li><pre><a name="63"></a> <span class="name">Result</span> : <span class="keyword">in</span> <span class="keyword">out</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:49:9" title="defined at generic_line_parser.ads:49:9">Config_Data</a>); </pre></li>
|
||||||
|
<li><pre><a name="64"></a> </pre></li>
|
||||||
|
<li><pre><a name="65"></a> <span class="keyword">type</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:65:9" title="defined at generic_line_parser.ads:65:9">Parameter_Descriptor</a> <span class="keyword">is</span> </pre></li>
|
||||||
|
<li><pre><a name="66"></a> <span class="keyword">record</span> </pre></li>
|
||||||
|
<li><pre><a name="67"></a> <span class="name">Name</span> : Unbounded_String; <span class="comment">-- Parameter name</span> </pre></li>
|
||||||
|
<li><pre><a name="68"></a> <span class="name">Default</span> : Unbounded_String; <span class="comment">-- Default value used if not on C.L.</span> </pre></li>
|
||||||
|
<li><pre><a name="69"></a> <span class="name">Mandatory</span> : Boolean; <span class="comment">-- Parameter MUST be given</span> </pre></li>
|
||||||
|
<li><pre><a name="70"></a> <span class="name">Only_Once</span> : Boolean; <span class="comment">-- Parameter MUST NOT be given more than once</span> </pre></li>
|
||||||
|
<li><pre><a name="71"></a> <span class="name">Callback</span> : <a href="generic_line_parser.ads.html#generic_line_parser.ads:60:9" title="defined at generic_line_parser.ads:60:9">Parameter_Callback</a>; <span class="comment">-- Called when parameter found</span> </pre></li>
|
||||||
|
<li><pre><a name="72"></a> <span class="keyword">end</span> <span class="keyword">record</span>; </pre></li>
|
||||||
|
<li><pre><a name="73"></a> <span class="comment">-- <description>Record holding the description of a parameter. The fields</span> </pre></li>
|
||||||
|
<li><pre><a name="74"></a> <span class="comment">-- should be self-explenatory (I hope). The only field that needs some</span> </pre></li>
|
||||||
|
<li><pre><a name="75"></a> <span class="comment">-- explanation is Name since it allows to specify more than one</span> </pre></li>
|
||||||
|
<li><pre><a name="76"></a> <span class="comment">-- name for each parameter. The syntax is very simple: just separate</span> </pre></li>
|
||||||
|
<li><pre><a name="77"></a> <span class="comment">-- the names with commas. For example, if Name is "f,filename,input"</span> </pre></li>
|
||||||
|
<li><pre><a name="78"></a> <span class="comment">-- one can use on the command line, with the same effect f=/tmp/a.txt or</span> </pre></li>
|
||||||
|
<li><pre><a name="79"></a> <span class="comment">-- filename=/tmp/a.txt or input=/tmp/a.txt. Spaces at both ends of</span> </pre></li>
|
||||||
|
<li><pre><a name="80"></a> <span class="comment">-- the label name are trimmed, so that, for example, "f,filename,input"</span> </pre></li>
|
||||||
|
<li><pre><a name="81"></a> <span class="comment">-- is equivalent to "f , filename ,input "</span> </pre></li>
|
||||||
|
<li><pre><a name="82"></a> <span class="comment">-- </description></span> </pre></li>
|
||||||
|
<li><pre><a name="83"></a> </pre></li>
|
||||||
|
<li><pre><a name="84"></a> </pre></li>
|
||||||
|
<li><pre><a name="85"></a> <span class="keyword">type</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:85:9" title="defined at generic_line_parser.ads:85:9">Parameter_Descriptor_Array</a> <span class="keyword">is</span> </pre></li>
|
||||||
|
<li><pre><a name="86"></a> <span class="keyword">array</span> (Natural <span class="keyword">range</span> <>) <span class="keyword">of</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:65:9" title="defined at generic_line_parser.ads:65:9">Parameter_Descriptor</a>; </pre></li>
|
||||||
|
<li><pre><a name="87"></a> </pre></li>
|
||||||
|
<li><pre><a name="88"></a> <span class="comment">-- Main exported method. It parses the command line and it writes</span> </pre></li>
|
||||||
|
<li><pre><a name="89"></a> <span class="comment">-- the result in Result. If some error is encountered, Bad_Command</span> </pre></li>
|
||||||
|
<li><pre><a name="90"></a> <span class="comment">-- is raised with an explicative exception message. Help_Line,</span> </pre></li>
|
||||||
|
<li><pre><a name="91"></a> <span class="comment">-- if not empty, is written to Help_Output in case of error.</span> </pre></li>
|
||||||
|
<li><pre><a name="92"></a> <span class="keyword">procedure</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:92:14" title="defined at generic_line_parser.ads:92:14">Parse_Command_Line</a> </pre></li>
|
||||||
|
<li><pre><a name="93"></a> (<a href="generic_line_parser.ads.html#generic_line_parser.ads:93:7" title="defined at generic_line_parser.ads:93:7">Parameters</a> : <span class="keyword">in</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:85:9" title="defined at generic_line_parser.ads:85:9">Parameter_Descriptor_Array</a>; </pre></li>
|
||||||
|
<li><pre><a name="94"></a> <a href="generic_line_parser.ads.html#generic_line_parser.ads:94:7" title="defined at generic_line_parser.ads:94:7">Result</a> : <span class="keyword">out</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:49:9" title="defined at generic_line_parser.ads:49:9">Config_Data</a>; </pre></li>
|
||||||
|
<li><pre><a name="95"></a> <a href="generic_line_parser.ads.html#generic_line_parser.ads:95:7" title="defined at generic_line_parser.ads:95:7">Help_Line</a> : <span class="keyword">in</span> String := <span class="string">""</span>; </pre></li>
|
||||||
|
<li><pre><a name="96"></a> <a href="generic_line_parser.ads.html#generic_line_parser.ads:96:7" title="defined at generic_line_parser.ads:96:7">Help_Output</a> : <span class="keyword">in</span> Ada.Text_IO.File_Type := Ada.Text_IO.Standard_Error); </pre></li>
|
||||||
|
<li><pre><a name="97"></a> </pre></li>
|
||||||
|
<li><pre><a name="98"></a> <a href="generic_line_parser.ads.html#generic_line_parser.ads:98:4" title="defined at generic_line_parser.ads:98:4">Bad_Command</a> : <span class="keyword">exception</span>; </pre></li>
|
||||||
|
<li><pre><a name="99"></a> </pre></li>
|
||||||
|
<li><pre><a name="100"></a> </pre></li>
|
||||||
|
<li><pre><a name="101"></a> <span class="comment">-- Convenient conversion function to Float that raise Bad_Command if</span> </pre></li>
|
||||||
|
<li><pre><a name="102"></a> <span class="comment">-- the argument has not a valid syntax</span> </pre></li>
|
||||||
|
<li><pre><a name="103"></a> <span class="keyword">function</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:103:13" title="defined at generic_line_parser.ads:103:13">To_Float</a> (<a href="generic_line_parser.ads.html#generic_line_parser.ads:103:23" title="defined at generic_line_parser.ads:103:23">X</a> : Unbounded_String) </pre></li>
|
||||||
|
<li><pre><a name="104"></a> <span class="keyword">return</span> Float; </pre></li>
|
||||||
|
<li><pre><a name="105"></a> </pre></li>
|
||||||
|
<li><pre><a name="106"></a> <span class="comment">-- Convenient conversion function to Float that raise Bad_Command if</span> </pre></li>
|
||||||
|
<li><pre><a name="107"></a> <span class="comment">-- the argument has not a valid syntax</span> </pre></li>
|
||||||
|
<li><pre><a name="108"></a> <span class="keyword">function</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:108:13" title="defined at generic_line_parser.ads:108:13">To_Natural</a> (<a href="generic_line_parser.ads.html#generic_line_parser.ads:108:25" title="defined at generic_line_parser.ads:108:25">X</a> : Unbounded_String) </pre></li>
|
||||||
|
<li><pre><a name="109"></a> <span class="keyword">return</span> Natural; </pre></li>
|
||||||
|
<li><pre><a name="110"></a> </pre></li>
|
||||||
|
<li><pre><a name="111"></a><span class="keyword">end</span> <a href="generic_line_parser.ads.html#generic_line_parser.ads:57:9" title="defined at generic_line_parser.ads:57:9">Generic_Line_Parser</a>; </pre></li>
|
||||||
|
</ol></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,408 @@
|
|||||||
|
body
|
||||||
|
{
|
||||||
|
background: #F4F4F4;
|
||||||
|
font-family: arial, verdana;
|
||||||
|
font-size: 90%;
|
||||||
|
margin: 0px 0px 10px 205px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2
|
||||||
|
{
|
||||||
|
padding: 0px 0px 0px 5px;
|
||||||
|
margin: 0px;
|
||||||
|
font-variant: small-caps;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3,
|
||||||
|
h4
|
||||||
|
{
|
||||||
|
font-size: 1.0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link,
|
||||||
|
a:active,
|
||||||
|
a:visited
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.hide:link,
|
||||||
|
a.hide:active,
|
||||||
|
a.hide:hover,
|
||||||
|
a.hide:visited
|
||||||
|
{
|
||||||
|
color: black;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.topBar
|
||||||
|
{
|
||||||
|
position: fixed;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
margin-left: 193px;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
z-index: 1;
|
||||||
|
background: transparent url(../support/images/menubarbottom.png) repeat-x bottom;
|
||||||
|
}
|
||||||
|
div.topBarInside
|
||||||
|
{
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
width: 100%;
|
||||||
|
background: transparent url(../support/images/menubar.png) repeat-x top;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.topBarLinks
|
||||||
|
{
|
||||||
|
z-index: 1;
|
||||||
|
padding: 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 10px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate page layout */
|
||||||
|
div#leftSide
|
||||||
|
{
|
||||||
|
position: fixed;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 205px;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
padding-bottom: 31px;
|
||||||
|
background: transparent url(../support/images/sidebarframebottom.png) no-repeat bottom;
|
||||||
|
z-index: 20;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#leftSide div#leftSideInside
|
||||||
|
{
|
||||||
|
width: 205px;
|
||||||
|
padding-top: 5px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 0px;
|
||||||
|
background: url(../support/images/sidebarframe.png) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#leftSideInside div
|
||||||
|
{
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#leftSideInside .button
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
width: 185px;
|
||||||
|
background: transparent url(../support/images/nav1_btn_up.png) no-repeat right;
|
||||||
|
height: 27px;
|
||||||
|
padding: 3px 0px 0px 5px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
div#leftSideInside a .button
|
||||||
|
{
|
||||||
|
color: #2020A0;
|
||||||
|
}
|
||||||
|
div#leftSideInside a:hover .button
|
||||||
|
{
|
||||||
|
color: #A02020;
|
||||||
|
background: transparent url(../support/images/nav1_btn_mo.png) no-repeat right;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#leftSideInside a
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
div#leftSideInside i .button2,
|
||||||
|
div#leftSideInside a .button2
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
margin: -6px 0px 0px 0px;
|
||||||
|
height: 26px;
|
||||||
|
width: 183px;
|
||||||
|
padding: 5px 0px 0px 5px;
|
||||||
|
background: transparent url(../support/images/nav2_btn_up.png) no-repeat right 0px;
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: inside;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
div#leftSideInside i .button2
|
||||||
|
{
|
||||||
|
color: #802020;
|
||||||
|
}
|
||||||
|
div#leftSideInside a .button2
|
||||||
|
{
|
||||||
|
color: #2020A0;
|
||||||
|
}
|
||||||
|
div#leftSideInside a:hover .button2
|
||||||
|
{
|
||||||
|
color: #A02020;
|
||||||
|
background: transparent url(../support/images/nav2_btn_mo.png) no-repeat right 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rightSide
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
width: 205px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
padding: 0px;
|
||||||
|
padding-bottom: 31px;
|
||||||
|
background: transparent url(../support/images/rightsidebottom.png) no-repeat bottom;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
div#rightSide div#rightSideInside
|
||||||
|
{
|
||||||
|
width: 205px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-left: 12px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 0px;
|
||||||
|
background: url(../support/images/rightside.png) repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#Index ul
|
||||||
|
{
|
||||||
|
margin: 2px 0px 0px 0px;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
div#Index li
|
||||||
|
{
|
||||||
|
width: 193px;
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: outside;
|
||||||
|
border-top: 1px dotted #c0c0c0;
|
||||||
|
}
|
||||||
|
div#Index li a
|
||||||
|
{
|
||||||
|
color: #2020A0;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
div#Index li a:hover
|
||||||
|
{
|
||||||
|
color: #E04040;
|
||||||
|
}
|
||||||
|
div#Index li.package-spec a
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/package-spec.png) no-repeat 3px 0px;
|
||||||
|
}
|
||||||
|
div#Index li.task-spec,
|
||||||
|
div#Index li.protected-spec,
|
||||||
|
div#Index li.var-spec
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/variable-spec.png) no-repeat 3px 0px;
|
||||||
|
}
|
||||||
|
div#Index li.class-spec,
|
||||||
|
div#Index li.task-type-spec,
|
||||||
|
div#Index li.protected-type-spec,
|
||||||
|
div#Index li.type-spec
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/type-spec.png) no-repeat 3px 0px;
|
||||||
|
}
|
||||||
|
div#Index li.subp-spec
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/subprogram-spec.png) no-repeat 3px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles within each region */
|
||||||
|
|
||||||
|
#documentation
|
||||||
|
{
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
padding: 0px 210px 10px 0px;
|
||||||
|
}
|
||||||
|
div.title,
|
||||||
|
div.titleTopBar
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
padding: 0px 0px 0px 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-variant: small-caps;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
div.title
|
||||||
|
{
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
div.titleTopBar
|
||||||
|
{
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.subprograms
|
||||||
|
{
|
||||||
|
font-size: 90%;
|
||||||
|
margin: 10px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.subprograms .class
|
||||||
|
{
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.subprograms .name
|
||||||
|
{
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
div.subprograms h3
|
||||||
|
{
|
||||||
|
background: #dae3fe;
|
||||||
|
padding: 0px 0px 0px 5px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
div.subprograms h4
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
div.subprograms div.profile
|
||||||
|
{
|
||||||
|
font-family: courier new, courier;
|
||||||
|
padding: 5px 5px 5px 5px;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
div.subprograms div.details
|
||||||
|
{
|
||||||
|
font-family: courier new, courier;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
background: #fafaff;
|
||||||
|
}
|
||||||
|
div.subprograms div.details div
|
||||||
|
{
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
div.subprograms div.details table
|
||||||
|
{
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
div.subprograms div.details span.keyword
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
color: #970505;
|
||||||
|
}
|
||||||
|
div.subprograms div.details span.string
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
color: #0A9988;
|
||||||
|
}
|
||||||
|
div.subprograms div.details span.comment
|
||||||
|
{
|
||||||
|
color: #209020;
|
||||||
|
}
|
||||||
|
div.subprograms div.comment
|
||||||
|
{
|
||||||
|
border-top: 1px dotted #c0c0c0;
|
||||||
|
background: white;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
div.subprograms div.comment *
|
||||||
|
{
|
||||||
|
margin: 0px;
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.subprograms .type,
|
||||||
|
div.subprograms .type * { padding-left: 0px;
|
||||||
|
font-weight: normal; }
|
||||||
|
div.subprograms div.entries
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
}
|
||||||
|
div.subprograms div.parameters,
|
||||||
|
div.subprograms div.parameters
|
||||||
|
{
|
||||||
|
font-family: courier new, courier;
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.subprograms div.parameters div,
|
||||||
|
div.subprograms div.details div { padding: 0px 0px 0px 0px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
border: 0px;}
|
||||||
|
div.entity
|
||||||
|
{
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
div.classroot,
|
||||||
|
div.classtree
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
div.classroot
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/tree_root.png) no-repeat left 0px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
div.classtree
|
||||||
|
{
|
||||||
|
background: transparent url(../support/images/tree_item.png) no-repeat left 0px;
|
||||||
|
}
|
||||||
|
div.classtreechildren
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
top: -4px;
|
||||||
|
margin: 0px 0px 0px 8px;
|
||||||
|
padding: 0px 0px 7px 0px;
|
||||||
|
background: transparent url(../support/images/treechildren_bg_bottom.png) no-repeat left bottom;
|
||||||
|
}
|
||||||
|
div.classtreechildreninside
|
||||||
|
{
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
padding: 0px 0px 5px 8px;
|
||||||
|
background: transparent url(../support/images/treechildren_bg.png) repeat-y left;
|
||||||
|
}
|
||||||
|
div.classroot h3,
|
||||||
|
div.classtree h3
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
height: 30px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 4px 0px 0px 15px;
|
||||||
|
margin: 0px 0px -6px 0px;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For printing we do not want the table of contents nor the index */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
|
||||||
|
body { margin: 10px; }
|
||||||
|
|
||||||
|
#rightSide { display: none; }
|
||||||
|
|
||||||
|
#leftSide { display: none; }
|
||||||
|
|
||||||
|
#documentation { margin: 10px; }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,226 @@
|
|||||||
|
myGetAttribute = function (elt, attribute) {
|
||||||
|
if (attribute == "class") attribute = "className";
|
||||||
|
return elt[attribute];
|
||||||
|
}
|
||||||
|
|
||||||
|
mySetAttribute = function (elt, attribute, value) {
|
||||||
|
if (attribute == "class") attribute = "className";
|
||||||
|
elt[attribute] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHidingLinks() {
|
||||||
|
onloadDoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onloadDoc() {
|
||||||
|
if (!document.getElementsByTagName) { return; }
|
||||||
|
if (!document.getElementById) { return; }
|
||||||
|
var main = document.getElementById ('leftSideInside');
|
||||||
|
var link1, link2;
|
||||||
|
|
||||||
|
setLinksForTag ('h2', '');
|
||||||
|
link1 = setLinksForTag ('h3', '');
|
||||||
|
link2 = setLinksForTag ('h4', 'hidden');
|
||||||
|
|
||||||
|
if (link1 | link2) {
|
||||||
|
div=document.createElement('div');
|
||||||
|
main.appendChild (div);
|
||||||
|
|
||||||
|
div=document.createElement('div');
|
||||||
|
div.setAttribute ('class', 'button');
|
||||||
|
div.setAttribute ('className', 'button'); /* for Internet Explorer */
|
||||||
|
text=document.createTextNode('Unfold');
|
||||||
|
div.appendChild (text);
|
||||||
|
lnk=document.createElement ("a");
|
||||||
|
lnk.setAttribute ('href', '#');
|
||||||
|
lnk.onclick = function () {showAllTags ('h3'); return false;}
|
||||||
|
lnk.appendChild (div);
|
||||||
|
main.appendChild (lnk);
|
||||||
|
|
||||||
|
var h4s = document.getElementsByTagName ('h4');
|
||||||
|
if (h4s.length > 0) {
|
||||||
|
div=document.createElement('div');
|
||||||
|
div.setAttribute ('class', 'button');
|
||||||
|
div.setAttribute ('className', 'button'); /* for Internet Explorer */
|
||||||
|
text=document.createTextNode('Unfold all');
|
||||||
|
div.appendChild (text);
|
||||||
|
lnk=document.createElement ("a");
|
||||||
|
lnk.setAttribute ('href', '#');
|
||||||
|
lnk.onclick = function () {showAllTags ('h3'); showAllTags ('h4'); return false;}
|
||||||
|
lnk.appendChild (div);
|
||||||
|
main.appendChild (lnk);
|
||||||
|
}
|
||||||
|
|
||||||
|
div=document.createElement('div');
|
||||||
|
div.setAttribute ('class', 'button');
|
||||||
|
div.setAttribute ('className', 'button'); /* for Internet Explorer */
|
||||||
|
text=document.createTextNode('Fold all');
|
||||||
|
div.appendChild (text);
|
||||||
|
lnk=document.createElement ("a");
|
||||||
|
lnk.setAttribute ('href', '#');
|
||||||
|
lnk.onclick = function () {hideAllTags ('h4'); hideAllTags ('h3'); return false;}
|
||||||
|
lnk.appendChild (div);
|
||||||
|
main.appendChild (lnk);
|
||||||
|
}
|
||||||
|
|
||||||
|
tags=document.getElementsByTagName('a');
|
||||||
|
for (var j=0; j<tags.length; j++) {
|
||||||
|
var href=tags[j].getAttribute ('href');
|
||||||
|
if (href == null) continue;
|
||||||
|
if ((href != '#') && (href.indexOf('#') > -1)) {
|
||||||
|
tags[j].onclick = function() {showLocationFromA(this); return true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should open a referenced entity
|
||||||
|
ref = document.location.hash;
|
||||||
|
if (ref != '') {
|
||||||
|
if (ref.indexOf('#') > -1) {
|
||||||
|
ref = ref.substr (1);
|
||||||
|
showLocation (ref);
|
||||||
|
elem = document.getElementById (ref);
|
||||||
|
if (elem) window.scrollTo (0,elem.offsetTop);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortElem(a,b)
|
||||||
|
{
|
||||||
|
return a[0].toLowerCase() > b[0].toLowerCase() ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printIndexList (names) {
|
||||||
|
if (names.length > 1) {
|
||||||
|
names.sort (sortElem);
|
||||||
|
document.write ('<ul>');
|
||||||
|
for (var j = 0; j < names.length; j++) {
|
||||||
|
if (names[j][0] != 'dummy') {
|
||||||
|
document.write ('<li class="'+names[j][2]+'"><a href="#'+names[j][1]+'" onclick="showLocation(\''+names[j][1]+'\')">'+names[j][0]+'</a></li>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.write ('</ul>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLinksForTag (tag, defaultstate) {
|
||||||
|
var titles = document.getElementsByTagName (tag);
|
||||||
|
|
||||||
|
for (var i=0; i<titles.length; i++){
|
||||||
|
if (canToggle (titles[i])) {
|
||||||
|
// insert <a href="#" onclick="return hide(this)">▼</a>
|
||||||
|
text=document.createTextNode('▼');
|
||||||
|
lnk=document.createElement("a");
|
||||||
|
lnk.setAttribute ('href', '#');
|
||||||
|
lnk.setAttribute ('class', 'hide');
|
||||||
|
lnk.setAttribute ('className', 'hide'); /* for Internet Explorer */
|
||||||
|
lnk.appendChild(text);
|
||||||
|
lnk.onclick = function () {toggle(this); return false;}
|
||||||
|
titles[i].insertBefore (lnk, titles[i].firstChild);
|
||||||
|
if (defaultstate == 'hidden')
|
||||||
|
toggle (lnk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return titles.length > 0;
|
||||||
|
}
|
||||||
|
function showLocationFromA (tag) {
|
||||||
|
var href = tag.getAttribute('href');
|
||||||
|
url = href.substr (0, href.indexOf('#'));
|
||||||
|
while (url.indexOf('/') > -1) url = url.substr (url.indexOf('/') + 1);
|
||||||
|
myurl = document.location.pathname;
|
||||||
|
while (myurl.indexOf('/') > -1) myurl = myurl.substr (myurl.indexOf('/') + 1);
|
||||||
|
if ((url != myurl) && (url != '')) return true;
|
||||||
|
href = href.substr (href.indexOf('#') + 1);
|
||||||
|
showLocation (href);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLocation (loc) {
|
||||||
|
var links = document.getElementsByTagName('a');
|
||||||
|
for (var j=0; j < links.length; j++) {
|
||||||
|
if (links[j].getAttribute ('name') == loc) {
|
||||||
|
var parent = links[j].parentNode;
|
||||||
|
while (parent != document) {
|
||||||
|
var elem = parent.firstChild;
|
||||||
|
if (elem.firstChild != null)
|
||||||
|
if (elem.firstChild.nodeValue == '►')
|
||||||
|
toggle (elem);
|
||||||
|
if (parent.tagName.toLowerCase() == 'div') {
|
||||||
|
for (var k=0; k < parent.childNodes.length; k++) {
|
||||||
|
if (parent.childNodes[k].nodeType == 1 &&
|
||||||
|
parent.childNodes[k].firstChild != null &&
|
||||||
|
parent.childNodes[k].firstChild.nodeType == 1 &&
|
||||||
|
parent.childNodes[k].firstChild.tagName.toLowerCase() == 'a') {
|
||||||
|
elem = parent.childNodes[k].firstChild;
|
||||||
|
if (elem.firstChild != null)
|
||||||
|
if (elem.firstChild.nodeValue == '►')
|
||||||
|
toggle (elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideAllTags (tag) {
|
||||||
|
if (!document.getElementsByTagName) { return; }
|
||||||
|
var titles = document.getElementsByTagName (tag);
|
||||||
|
for (var i=0; i<titles.length; i++){
|
||||||
|
if (titles[i].firstChild.firstChild.nodeValue == '▼') {
|
||||||
|
toggle (titles[i].firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAllTags (tag) {
|
||||||
|
if (!document.getElementsByTagName) { return; }
|
||||||
|
var titles = document.getElementsByTagName (tag);
|
||||||
|
for (var i=0; i<titles.length; i++){
|
||||||
|
if (titles[i].firstChild.firstChild.nodeValue == '►') {
|
||||||
|
toggle (titles[i].firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function canToggle (elem) {
|
||||||
|
var children = elem.parentNode.childNodes;
|
||||||
|
|
||||||
|
for (var j = 0; j < children.length; j++) {
|
||||||
|
var el = children[j];
|
||||||
|
if (el.nodeType == 1 &&
|
||||||
|
el.tagName.toLowerCase() != 'script' &&
|
||||||
|
el.tagName.toLowerCase() != 'h2' &&
|
||||||
|
el.tagName.toLowerCase() != 'h3' &&
|
||||||
|
el.tagName.toLowerCase() != 'h4') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle (elem) {
|
||||||
|
var children = elem.parentNode.parentNode.childNodes;
|
||||||
|
var next_display;
|
||||||
|
|
||||||
|
if (elem.childNodes[0].nodeValue == '▼') {
|
||||||
|
next_display = 'none';
|
||||||
|
elem.childNodes[0].nodeValue = '►';
|
||||||
|
} else {
|
||||||
|
next_display = 'block';
|
||||||
|
elem.childNodes[0].nodeValue = '▼';
|
||||||
|
}
|
||||||
|
for (var j = 0; j < children.length; j++) {
|
||||||
|
var el = children[j];
|
||||||
|
if (el.nodeType == 1 &&
|
||||||
|
el.tagName.toLowerCase() != 'script' &&
|
||||||
|
el.tagName.toLowerCase() != 'h2' &&
|
||||||
|
el.tagName.toLowerCase() != 'h3' &&
|
||||||
|
el.tagName.toLowerCase() != 'h4') {
|
||||||
|
el.style.display = next_display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
After Width: | Height: | Size: 1002 B |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 423 B |
After Width: | Height: | Size: 227 B |
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 532 B |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 197 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 483 B |
After Width: | Height: | Size: 407 B |
@ -0,0 +1,43 @@
|
|||||||
|
div.summary:before
|
||||||
|
{
|
||||||
|
content: "Summary: ";
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.summary
|
||||||
|
{
|
||||||
|
border-bottom: 1px dotted #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.description:before
|
||||||
|
{
|
||||||
|
content: "Description: ";
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.description
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
border-bottom: 1px dotted #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.parameter *
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
color: #444;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.exception:before
|
||||||
|
{
|
||||||
|
content: "Exception: ";
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.seealso:before
|
||||||
|
{
|
||||||
|
content: "See also: ";
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.seealso
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript"/>
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Global Class Inheritance Trees
|
||||||
|
</title>
|
||||||
|
<link rel='stylesheet' href='support/docgen.css' type='text/css'/>
|
||||||
|
<script src='support/docgen.js' type='text/javascript' charset='utf-8'></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onloadDoc();">
|
||||||
|
<div id='leftSide'>
|
||||||
|
<div id='leftSideInside'>
|
||||||
|
<div id='header'>
|
||||||
|
<h2 class="button">Documentation</h2>
|
||||||
|
<a href='index.html'><div class="button2">Table of Contents</div></a>
|
||||||
|
|
||||||
|
<i><div class="button2">Class Inheritance Tree</div></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='title'>
|
||||||
|
Global Class Inheritance Trees
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,70 @@
|
|||||||
|
This directory contains a very basic example of usage of the generic
|
||||||
|
package.
|
||||||
|
|
||||||
|
Our goal
|
||||||
|
========
|
||||||
|
|
||||||
|
We want to write the line parsing code for a program that is supposed
|
||||||
|
to contact a remote host, authenticating with a username and,
|
||||||
|
possibly, a password. By default the remote host listens on port
|
||||||
|
4242, but a different port can be specified. The main procedure in
|
||||||
|
basic_example-main.adb implements the required command line parsing
|
||||||
|
and prints the result on the standard output.
|
||||||
|
|
||||||
|
More precisely, the parameters on the command line are to be specified
|
||||||
|
as follows
|
||||||
|
|
||||||
|
* The host address will be specified with the parameter "host" (only
|
||||||
|
numerical addresses are accepted)
|
||||||
|
|
||||||
|
* The optional port will be specified with the parameter "port", if
|
||||||
|
not specified, the port defaults to 4242
|
||||||
|
|
||||||
|
* The username can be specified, equivalently, with the parameter
|
||||||
|
"user" or with the parameter "username"
|
||||||
|
|
||||||
|
* The optional password can be specified, equivalently, with the parameter
|
||||||
|
"pwd" or with the parameter "password". If not specified, the
|
||||||
|
password defaults to ""
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Therefore, for example, the following command lines are accepted
|
||||||
|
|
||||||
|
basic_example-main host=196.18.1.34 user=pippo
|
||||||
|
|
||||||
|
Contact host 196.18.1.34 on port 4242 with username pippo and no password
|
||||||
|
|
||||||
|
basic_example-main host=196.18.1.34 username=pippo
|
||||||
|
|
||||||
|
Equivalent to the command line above
|
||||||
|
|
||||||
|
basic_example-main host=196.18.1.34 user=pippo pwd=pluto
|
||||||
|
|
||||||
|
Contact host 196.18.1.34 with username pippo and password pluto
|
||||||
|
|
||||||
|
basic_example-main host=196.18.1.34 user=pippo password=pluto
|
||||||
|
|
||||||
|
Equivalent to the command line above
|
||||||
|
|
||||||
|
basic_example-main host=196.18.1.34 port=12345 user=pippo
|
||||||
|
|
||||||
|
Contact host 196.18.1.34 on port 12345 with username pippo and no password
|
||||||
|
|
||||||
|
|
||||||
|
Structure of the program
|
||||||
|
========================
|
||||||
|
|
||||||
|
It is very simple:
|
||||||
|
|
||||||
|
* basic_example-main.adb
|
||||||
|
|
||||||
|
Contains the main procedure
|
||||||
|
|
||||||
|
* basic_example-parameters.adb
|
||||||
|
|
||||||
|
Defines a record that holds the four parameters (host, port,
|
||||||
|
username and password) that can be specified by the user. It
|
||||||
|
defines also procedures that set the four parameters and that
|
||||||
|
can be used as callbacks for the line parsers.
|
@ -0,0 +1,74 @@
|
|||||||
|
with Ada.Text_IO;
|
||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
with GNAT.Sockets;
|
||||||
|
|
||||||
|
with Generic_Line_Parser;
|
||||||
|
with Basic_Example.Parameters; -- Defines the record with the user parameters
|
||||||
|
|
||||||
|
procedure Basic_Example.Main is
|
||||||
|
use Ada.Strings;
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
use GNAT;
|
||||||
|
|
||||||
|
-- Convenient shorthand for the function that converts strings to
|
||||||
|
-- unbounded strings
|
||||||
|
function To_U (X : String) return Unbounded.Unbounded_String
|
||||||
|
renames Unbounded.To_Unbounded_String;
|
||||||
|
|
||||||
|
-- Instantiate a specific version of Generic_Line_Parser suited
|
||||||
|
-- for the User_Parameters record defined in Basic_Example.Parameters
|
||||||
|
package Line_Parser is
|
||||||
|
new Generic_Line_Parser (Parameters.User_Parameters);
|
||||||
|
|
||||||
|
-- Declare the array of parameter descriptors. Note that the
|
||||||
|
-- callbacks are set to the procedures declared in
|
||||||
|
-- Basic_Example.Parameters
|
||||||
|
Descriptors : Line_Parser.Parameter_Descriptor_Array :=
|
||||||
|
((Name => To_U ("host"),
|
||||||
|
Default => <>,
|
||||||
|
Mandatory => True,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Parameters.Set_Host'Access),
|
||||||
|
|
||||||
|
(Name => To_U ("port"),
|
||||||
|
Default => To_U ("4242"),
|
||||||
|
Mandatory => False,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Parameters.Set_Port'Access),
|
||||||
|
|
||||||
|
-- Both "user" and "username" are acceptable
|
||||||
|
(Name => To_U ("user,username"),
|
||||||
|
Default => <>,
|
||||||
|
Mandatory => True,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Parameters.Set_Username'Access),
|
||||||
|
|
||||||
|
-- Both "pwd" and "password" are acceptable
|
||||||
|
(Name => To_U ("pwd,password"),
|
||||||
|
Default => Unbounded.Null_Unbounded_String,
|
||||||
|
Mandatory => False,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Parameters.Set_Password'Access));
|
||||||
|
|
||||||
|
Param : Parameters.User_Parameters;
|
||||||
|
begin
|
||||||
|
Line_Parser.Parse_Command_Line
|
||||||
|
(Parameters => Descriptors,
|
||||||
|
Result => Param);
|
||||||
|
|
||||||
|
Ada.Text_IO.Put ("I am going to contact host '"
|
||||||
|
& Sockets.Image (Param.Host)
|
||||||
|
& "' on port "
|
||||||
|
& Sockets.Port_Type'Image (Param.Port)
|
||||||
|
& " with username '"
|
||||||
|
& Unbounded.To_String (Param.Username)
|
||||||
|
& "'");
|
||||||
|
|
||||||
|
if Param.Password = Unbounded.Null_Unbounded_String then
|
||||||
|
Ada.Text_IO.Put_Line (" and no password");
|
||||||
|
else
|
||||||
|
Ada.Text_IO.Put_Line (" and password '"
|
||||||
|
& Unbounded.To_String (Param.Password)
|
||||||
|
& "'");
|
||||||
|
end if;
|
||||||
|
end Basic_Example.Main;
|
@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
package body Basic_Example.Parameters is
|
||||||
|
use GNAT;
|
||||||
|
use Ada.Strings;
|
||||||
|
|
||||||
|
--------------
|
||||||
|
-- Set_Host --
|
||||||
|
--------------
|
||||||
|
|
||||||
|
procedure Set_Host
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Host := Sockets.Inet_Addr (Unbounded.To_String (Value));
|
||||||
|
end Set_Host;
|
||||||
|
|
||||||
|
--------------
|
||||||
|
-- Set_Port --
|
||||||
|
--------------
|
||||||
|
|
||||||
|
procedure Set_Port
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Port := Sockets.Port_Type'Value (Unbounded.To_String (Value));
|
||||||
|
end Set_Port;
|
||||||
|
|
||||||
|
------------------
|
||||||
|
-- Set_Username --
|
||||||
|
------------------
|
||||||
|
|
||||||
|
procedure Set_Username
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Username := Value;
|
||||||
|
end Set_Username;
|
||||||
|
|
||||||
|
------------------
|
||||||
|
-- Set_Password --
|
||||||
|
------------------
|
||||||
|
|
||||||
|
procedure Set_Password
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Password := Value;
|
||||||
|
end Set_Password;
|
||||||
|
|
||||||
|
end Basic_Example.Parameters;
|
@ -0,0 +1,38 @@
|
|||||||
|
with GNAT.Sockets;
|
||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
package Basic_Example.Parameters is
|
||||||
|
use GNAT;
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
type User_Parameters is
|
||||||
|
record
|
||||||
|
Host : Sockets.Inet_Addr_Type;
|
||||||
|
Port : Sockets.Port_Type;
|
||||||
|
Username : Unbounded_String;
|
||||||
|
Password : Unbounded_String;
|
||||||
|
end record;
|
||||||
|
-- Record that holds the paramters that can be specified by the user.
|
||||||
|
-- The following four procedures can be used as callbacks in an
|
||||||
|
-- instantiation of Generic_Line_Parser.
|
||||||
|
|
||||||
|
procedure Set_Host
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Port
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Username
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Password
|
||||||
|
(Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
end Basic_Example.Parameters;
|
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
package Basic_Example is
|
||||||
|
-- Root
|
||||||
|
end Basic_Example;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
project Gclp_examples is
|
||||||
|
|
||||||
|
for Object_Dir use "bin";
|
||||||
|
|
||||||
|
for Source_Dirs use ("..", ".", "Basic_Example");
|
||||||
|
|
||||||
|
for Main use ("basic_example-main.adb");
|
||||||
|
|
||||||
|
package Compiler is
|
||||||
|
for Default_Switches ("ada") use ("-gnat05", "-gnata", "-g");
|
||||||
|
end Compiler;
|
||||||
|
|
||||||
|
end Gclp_examples;
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
project Gclp is
|
||||||
|
|
||||||
|
for Object_Dir use "bin";
|
||||||
|
|
||||||
|
package Compiler is
|
||||||
|
-- for Default_Switches ("ada") use ("-gnat05", "-gnata", "-g");
|
||||||
|
for Default_Switches ("ada") use ("-gnata", "-g");
|
||||||
|
end Compiler;
|
||||||
|
|
||||||
|
end Gclp;
|
||||||
|
|
@ -0,0 +1,359 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- Generic Command Line Parser (gclp)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2012, Riccardo Bernardini
|
||||||
|
--
|
||||||
|
-- This file is part of gclp.
|
||||||
|
--
|
||||||
|
-- gclp 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.
|
||||||
|
--
|
||||||
|
-- gclp 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 gclp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
with Ada.Command_Line;
|
||||||
|
with Ada.Strings.Fixed;
|
||||||
|
with Ada.Text_IO;
|
||||||
|
with Ada.Containers.Ordered_Maps;
|
||||||
|
with Ada.Strings.Maps.Constants;
|
||||||
|
with Ada.Containers.Doubly_Linked_Lists;
|
||||||
|
|
||||||
|
use Ada;
|
||||||
|
use Ada.Strings;
|
||||||
|
use Ada.Strings.Fixed;
|
||||||
|
|
||||||
|
package body Generic_Line_Parser is
|
||||||
|
|
||||||
|
function To_S (X : Unbounded_String) return String
|
||||||
|
renames To_String;
|
||||||
|
|
||||||
|
function To_U (X : String) return Unbounded_String
|
||||||
|
renames To_Unbounded_String;
|
||||||
|
|
||||||
|
-- In order to handle parameter aliases (see comments in the specs)
|
||||||
|
-- we keep a table that maps parameter names to parameter "index"
|
||||||
|
package Name_To_Index_Maps is
|
||||||
|
new Ada.Containers.Ordered_Maps (Key_Type => Unbounded_String,
|
||||||
|
Element_Type => Natural);
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Case_Normalize --
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
-- If the user required case insensitive matching, force the
|
||||||
|
-- name to lower case
|
||||||
|
procedure Case_Normalize (Name : in out Unbounded_String) is
|
||||||
|
begin
|
||||||
|
if not Case_Sensitive then
|
||||||
|
Translate (Name, Maps.Constants.Lower_Case_Map);
|
||||||
|
end if;
|
||||||
|
end Case_Normalize;
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
-- Fill_Name_Table --
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
-- Fill the Parameter Name -> parameter index table with the
|
||||||
|
-- parameter names
|
||||||
|
procedure Fill_Name_Table (Parameters : in Parameter_Descriptor_Array;
|
||||||
|
Name_Table : in out Name_To_Index_Maps.Map)
|
||||||
|
is
|
||||||
|
package Name_Lists is
|
||||||
|
new Ada.Containers.Doubly_Linked_Lists (Unbounded_String);
|
||||||
|
|
||||||
|
use Name_Lists;
|
||||||
|
|
||||||
|
----------------
|
||||||
|
-- Parse_Name --
|
||||||
|
----------------
|
||||||
|
|
||||||
|
function Parse_Name (Name : Unbounded_String) return Name_Lists.List
|
||||||
|
is
|
||||||
|
------------------
|
||||||
|
-- Trimmed_Name --
|
||||||
|
------------------
|
||||||
|
|
||||||
|
function Trimmed_Name (Name : String)
|
||||||
|
return Unbounded_String
|
||||||
|
is
|
||||||
|
Trimmed : Unbounded_String;
|
||||||
|
begin
|
||||||
|
Trimmed := To_U (Fixed.Trim (Name, Both));
|
||||||
|
if Unbounded.Length (Trimmed) = 0 then
|
||||||
|
raise Constraint_Error
|
||||||
|
with "Empty alternative in label '" & Name & "'";
|
||||||
|
else
|
||||||
|
return Trimmed;
|
||||||
|
end if;
|
||||||
|
end Trimmed_Name;
|
||||||
|
|
||||||
|
Result : Name_Lists.List;
|
||||||
|
Buffer : String := To_S (Name);
|
||||||
|
First : Natural;
|
||||||
|
Comma_Pos : Natural;
|
||||||
|
begin
|
||||||
|
if Fixed.Index (Buffer, "=") /= 0 then
|
||||||
|
raise Constraint_Error with "Option label '" & Buffer & "' has '='";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if Buffer(Buffer'Last) = ',' then
|
||||||
|
raise Constraint_Error
|
||||||
|
with "Option label '" & Buffer & "' ends with ','";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
First := Buffer'First;
|
||||||
|
loop
|
||||||
|
pragma Assert (First <= Buffer'Last);
|
||||||
|
|
||||||
|
Comma_Pos := Fixed.Index (Buffer (First .. Buffer'Last), ",");
|
||||||
|
exit when Comma_Pos = 0;
|
||||||
|
|
||||||
|
if First = Comma_Pos then
|
||||||
|
-- First should always point to the beginning of a
|
||||||
|
-- label, therefore it cannot be Buffer(First) = ','
|
||||||
|
raise Constraint_Error
|
||||||
|
with "Wrong syntax in Option label '" & Buffer & "'";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
pragma Assert (Comma_Pos > First);
|
||||||
|
|
||||||
|
Result.Append (Trimmed_Name (Buffer(First .. Comma_Pos - 1)));
|
||||||
|
|
||||||
|
First := Comma_Pos + 1;
|
||||||
|
|
||||||
|
-- It cannot be First > Buffer'Last since Buffer(Comma_Pos) = '='
|
||||||
|
-- and Buffer(Buffer'Last) /= ','
|
||||||
|
pragma Assert (First <= Buffer'Last);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
pragma Assert (First <= Buffer'Last);
|
||||||
|
|
||||||
|
Result.Append (Trimmed_Name (Buffer (First .. Buffer'Last)));
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
end Parse_Name;
|
||||||
|
|
||||||
|
Option_Names : Name_Lists.List;
|
||||||
|
Position : Name_Lists.Cursor;
|
||||||
|
|
||||||
|
Name : Unbounded_String;
|
||||||
|
begin
|
||||||
|
for Idx in Parameters'Range loop
|
||||||
|
Option_Names := Parse_Name (Parameters (Idx).Name);
|
||||||
|
|
||||||
|
Position := Option_Names.First;
|
||||||
|
|
||||||
|
while Position /= No_Element loop
|
||||||
|
Name := Name_Lists.Element (Position);
|
||||||
|
Name_Lists.Next (Position);
|
||||||
|
|
||||||
|
Case_Normalize(Name);
|
||||||
|
|
||||||
|
if Name_Table.Contains (Name) then
|
||||||
|
raise Constraint_Error
|
||||||
|
with "Ambiguous label '" & To_S (Name) & "'";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Name_Table.Insert (Name, Idx);
|
||||||
|
end loop;
|
||||||
|
end loop;
|
||||||
|
end Fill_Name_Table;
|
||||||
|
|
||||||
|
|
||||||
|
----------------
|
||||||
|
-- To_Natural --
|
||||||
|
----------------
|
||||||
|
|
||||||
|
function To_Natural (X : Unbounded_String)
|
||||||
|
return Natural is
|
||||||
|
begin
|
||||||
|
if X = Null_Unbounded_String then
|
||||||
|
raise Bad_Command with "Invalid integer '" & To_S(X) & "'";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return Natural'Value (To_S (X));
|
||||||
|
end To_Natural;
|
||||||
|
|
||||||
|
--------------
|
||||||
|
-- To_Float --
|
||||||
|
--------------
|
||||||
|
|
||||||
|
function To_Float (X : Unbounded_String)
|
||||||
|
return Float is
|
||||||
|
begin
|
||||||
|
if X = Null_Unbounded_String then
|
||||||
|
raise Bad_Command with "Invalid Float '" & To_S(X) & "'";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return Float'Value (To_S (X));
|
||||||
|
end To_Float;
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Parse_Command_Line --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
procedure Parse_Command_Line
|
||||||
|
(Parameters : in Parameter_Descriptor_Array;
|
||||||
|
Result : out Config_Data;
|
||||||
|
Help_Line : in String := "";
|
||||||
|
Help_Output : in Ada.Text_IO.File_Type := Ada.Text_IO.Standard_Error) is
|
||||||
|
|
||||||
|
package String_Lists is
|
||||||
|
new Ada.Containers.Doubly_Linked_Lists (Unbounded_String);
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
-- Split_Parameter --
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
procedure Split_Parameter (Param : in String;
|
||||||
|
Name : out Unbounded_String;
|
||||||
|
Value : out Unbounded_String)
|
||||||
|
is
|
||||||
|
Idx : Natural;
|
||||||
|
begin
|
||||||
|
Idx := Index (Source => Param,
|
||||||
|
Pattern => "=");
|
||||||
|
|
||||||
|
if (Idx = 0) then
|
||||||
|
Name := To_U (Param);
|
||||||
|
Value := Null_Unbounded_String;
|
||||||
|
else
|
||||||
|
Name := To_U (Param (Param'First .. Idx - 1));
|
||||||
|
Value := To_U (Param (Idx + 1 .. Param'Last));
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Case_Normalize (Name);
|
||||||
|
end Split_Parameter;
|
||||||
|
|
||||||
|
function Missing_Message (Missing : String_Lists.List)
|
||||||
|
return String
|
||||||
|
is
|
||||||
|
function Join (Item : String_Lists.List) return String is
|
||||||
|
Result : Unbounded_String;
|
||||||
|
|
||||||
|
procedure Append (Pos : String_Lists.Cursor) is
|
||||||
|
begin
|
||||||
|
if Result /= Null_Unbounded_String then
|
||||||
|
Result := Result & ", ";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Result := Result & "'" & String_Lists.Element (Pos) & "'";
|
||||||
|
end Append;
|
||||||
|
begin
|
||||||
|
Item.Iterate (Append'Access);
|
||||||
|
|
||||||
|
return To_String(Result);
|
||||||
|
end Join;
|
||||||
|
|
||||||
|
use type Ada.Containers.Count_Type;
|
||||||
|
begin
|
||||||
|
if Missing.Length = 1 then
|
||||||
|
return "Missing mandatory option " & Join (Missing);
|
||||||
|
else
|
||||||
|
return "Missing mandatory options: " & Join (Missing);
|
||||||
|
end if;
|
||||||
|
end Missing_Message;
|
||||||
|
|
||||||
|
|
||||||
|
Found : array (Parameters'Range) of Boolean := (others => False);
|
||||||
|
|
||||||
|
Name : Unbounded_String;
|
||||||
|
Value : Unbounded_String;
|
||||||
|
|
||||||
|
use Name_To_Index_Maps;
|
||||||
|
|
||||||
|
Name_Table : Name_To_Index_Maps.Map;
|
||||||
|
Position : Name_To_Index_Maps.Cursor;
|
||||||
|
Param_Idx : Natural;
|
||||||
|
begin
|
||||||
|
Fill_Name_Table (Parameters, Name_Table);
|
||||||
|
|
||||||
|
for Pos in 1 .. Command_Line.Argument_Count loop
|
||||||
|
Split_Parameter (Command_Line.Argument (Pos), Name, Value);
|
||||||
|
|
||||||
|
Position := Name_Table.Find (Name);
|
||||||
|
|
||||||
|
if Position = No_Element then
|
||||||
|
raise Bad_Command with "Option '" & To_S (Name) & "' unknown";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Param_Idx := Name_To_Index_Maps.Element (Position);
|
||||||
|
|
||||||
|
if Found (Param_Idx) and then Parameters (Param_Idx).Only_Once then
|
||||||
|
raise Bad_Command with "Option '" & To_S (Name) & "' given twice";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Found (Param_Idx) := True;
|
||||||
|
Parameters (Param_Idx).Callback (Name => Name,
|
||||||
|
Value => Value,
|
||||||
|
Result => Result);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
declare
|
||||||
|
use type Name_To_Index_Maps.Cursor;
|
||||||
|
|
||||||
|
Missing : String_Lists.List;
|
||||||
|
Param_Idx : Natural;
|
||||||
|
Position : Name_To_Index_Maps.Cursor;
|
||||||
|
|
||||||
|
Reported : array (Parameters'Range) of Boolean := (others => False);
|
||||||
|
-- Reported(Idx) is true if the parameter with index Idx has
|
||||||
|
-- already processed as missing. We need this since we loop over
|
||||||
|
-- the option names and more than option can refer to the same
|
||||||
|
-- parameter.
|
||||||
|
begin
|
||||||
|
Position := Name_Table.First;
|
||||||
|
|
||||||
|
while Position /= Name_To_Index_Maps.No_Element loop
|
||||||
|
Param_Idx := Name_To_Index_Maps.Element (Position);
|
||||||
|
|
||||||
|
-- Ada.Text_IO.Put ("checking" & To_S(Parameters (Param_Idx).Name) & "->");
|
||||||
|
-- Ada.Text_IO.Put (Boolean'Image (Found (Param_Idx)));
|
||||||
|
-- Ada.Text_IO.Put_Line (" "& Boolean'Image (Reported (Param_Idx)));
|
||||||
|
|
||||||
|
if not Found (Param_Idx) and not Reported (Param_Idx) then
|
||||||
|
Reported (Param_Idx) := True;
|
||||||
|
|
||||||
|
case Parameters (Param_Idx).If_Missing is
|
||||||
|
when Die =>
|
||||||
|
Missing.Append (Name_To_Index_Maps.Key (Position));
|
||||||
|
|
||||||
|
when Use_Default =>
|
||||||
|
Parameters (Param_Idx).Callback
|
||||||
|
(Name => Parameters (Param_Idx).Name,
|
||||||
|
Value => Parameters (Param_Idx).Default,
|
||||||
|
Result => Result);
|
||||||
|
|
||||||
|
when Ignore =>
|
||||||
|
null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Name_To_Index_Maps.Next (Position);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
|
||||||
|
if not Missing.Is_Empty then
|
||||||
|
raise Bad_Command with Missing_Message (Missing);
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
exception
|
||||||
|
when Bad_Command =>
|
||||||
|
if Help_Line /= "" then
|
||||||
|
Ada.Text_IO.Put_Line (File => Help_Output,
|
||||||
|
Item => Help_Line);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
raise;
|
||||||
|
end Parse_Command_Line;
|
||||||
|
|
||||||
|
end Generic_Line_Parser;
|
@ -0,0 +1,149 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- Generic Command Line Parser (gclp)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2012, Riccardo Bernardini
|
||||||
|
--
|
||||||
|
-- This file is part of gclp.
|
||||||
|
--
|
||||||
|
-- gclp 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.
|
||||||
|
--
|
||||||
|
-- gclp 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 gclp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- <summary>
|
||||||
|
-- <p>This is a generic package implementing a simple-to-use command line
|
||||||
|
-- parser. Yes, I know, everyone makes his/her own command line parser...
|
||||||
|
-- so, I wrote mine. As they say, every open source project starts
|
||||||
|
-- with a programmer that schratches its own itch. So I did... If
|
||||||
|
-- you find this useful, you are welcome to use it.</p>
|
||||||
|
--
|
||||||
|
-- <p>The ideas behind this package are the following
|
||||||
|
--
|
||||||
|
-- <itemize>
|
||||||
|
-- <item> <p>Parameters are nominal, non positional. The syntax is of
|
||||||
|
-- "named parameter" type, that is, each command line parameter is
|
||||||
|
-- expected to have thefollowing format</p>
|
||||||
|
--
|
||||||
|
-- <center>label ['=' value]</center>
|
||||||
|
--
|
||||||
|
-- <p>where "label" is any string without '='.</p></item>
|
||||||
|
--
|
||||||
|
-- <item><p> Parsed value are written in a "configuration variable" whose type
|
||||||
|
-- is a formal parameter of this package. The values are written
|
||||||
|
-- in the configuration variable by using some callbacks provided
|
||||||
|
-- by caller.</p></item>
|
||||||
|
-- </itemize>
|
||||||
|
-- </p>
|
||||||
|
-- The names of the parameters are given to the parser in "parameter
|
||||||
|
-- description array" that is an array of records that specify
|
||||||
|
--
|
||||||
|
-- + The parameter name
|
||||||
|
--
|
||||||
|
-- + A default value (if needed)
|
||||||
|
--
|
||||||
|
-- + What to do if the parameter is missing
|
||||||
|
--
|
||||||
|
-- + If it can be specified more than once
|
||||||
|
--
|
||||||
|
-- + The callback function to be called when the parameter is found
|
||||||
|
--
|
||||||
|
-- In order to parse the command line it suffices to call Parse_Command_Line
|
||||||
|
-- giving as argument the array of parameter descriptors and the configuration
|
||||||
|
-- variable to be written. For every parameter found, the corresponding
|
||||||
|
-- callback function is called. If at the end of the parsing there are some
|
||||||
|
-- optional parameters that were missing from the command line, the
|
||||||
|
-- corresponding callbacks are called with the default parameter.
|
||||||
|
-- </summary>
|
||||||
|
|
||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
with Ada.Text_IO;
|
||||||
|
|
||||||
|
generic
|
||||||
|
type Config_Data (<>) is limited private;
|
||||||
|
-- The parameters read from the command line will be written in
|
||||||
|
-- a variable of this type
|
||||||
|
|
||||||
|
Case_Sensitive : Boolean := True;
|
||||||
|
-- Set this to False if you want case insensitive option matching.
|
||||||
|
-- For example, if you set this to False, "input", "Input", "INPUT"
|
||||||
|
-- and "InPuT" will be equivalent names for the option "input"
|
||||||
|
package Generic_Line_Parser is
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
type Parameter_Callback is
|
||||||
|
access procedure (Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out Config_Data);
|
||||||
|
|
||||||
|
type Missing_Action is (Die, Use_Default, Ignore);
|
||||||
|
-- Possibile alternatives about what to do if a parameter is missing
|
||||||
|
--
|
||||||
|
-- [Die] The parameter is mandatory. If it is missing, an
|
||||||
|
-- exception with explicative message is raised
|
||||||
|
--
|
||||||
|
-- [Use_Default] The parameter is optional. If it is missing, the
|
||||||
|
-- corresponding callback function is called with the
|
||||||
|
-- specified default value (see record
|
||||||
|
-- Parameter_Descriptor in the following)
|
||||||
|
--
|
||||||
|
-- [Ignore] The parameter is optional. If it is missing, nothing
|
||||||
|
-- is done
|
||||||
|
|
||||||
|
type Parameter_Descriptor is
|
||||||
|
record
|
||||||
|
Name : Unbounded_String; -- Parameter name
|
||||||
|
Default : Unbounded_String; -- Default value used if not on C.L.
|
||||||
|
If_Missing : Missing_Action; -- What to do if parameter missing
|
||||||
|
Only_Once : Boolean; -- Parameter MUST NOT be given more than once
|
||||||
|
Callback : Parameter_Callback; -- Called when parameter found
|
||||||
|
end record;
|
||||||
|
-- <description>Record holding the description of a parameter. The fields
|
||||||
|
-- should be self-explenatory (I hope). The only field that needs some
|
||||||
|
-- explanation is Name since it allows to specify more than one
|
||||||
|
-- name for each parameter. The syntax is very simple: just separate
|
||||||
|
-- the names with commas. For example, if Name is "f,filename,input"
|
||||||
|
-- one can use on the command line, with the same effect f=/tmp/a.txt or
|
||||||
|
-- filename=/tmp/a.txt or input=/tmp/a.txt. Spaces at both ends of
|
||||||
|
-- the label name are trimmed, so that, for example, "f,filename,input"
|
||||||
|
-- is equivalent to "f , filename ,input "
|
||||||
|
-- </description>
|
||||||
|
|
||||||
|
|
||||||
|
type Parameter_Descriptor_Array is
|
||||||
|
array (Natural range <>) of Parameter_Descriptor;
|
||||||
|
|
||||||
|
|
||||||
|
procedure Parse_Command_Line
|
||||||
|
(Parameters : in Parameter_Descriptor_Array;
|
||||||
|
Result : out Config_Data;
|
||||||
|
Help_Line : in String := "";
|
||||||
|
Help_Output : in Ada.Text_IO.File_Type := Ada.Text_IO.Standard_Error);
|
||||||
|
-- Main exported method. It parses the command line and it writes
|
||||||
|
-- the result in Result. If some error is encountered, Bad_Command
|
||||||
|
-- is raised with an explicative exception message. If Help_Line is
|
||||||
|
-- not empty, it is written to Help_Output in case of error.
|
||||||
|
|
||||||
|
Bad_Command : exception;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function To_Float (X : Unbounded_String)
|
||||||
|
return Float;
|
||||||
|
-- Convenient conversion function to Float that raise Bad_Command if
|
||||||
|
-- the argument has not a valid syntax
|
||||||
|
|
||||||
|
function To_Natural (X : Unbounded_String)
|
||||||
|
return Natural;
|
||||||
|
-- Convenient conversion function to Float that raise Bad_Command if
|
||||||
|
-- the argument has not a valid syntax
|
||||||
|
|
||||||
|
end Generic_Line_Parser;
|
@ -0,0 +1,110 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- Generic Command Line Parser (gclp)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2012, Riccardo Bernardini
|
||||||
|
--
|
||||||
|
-- This file is part of gclp.
|
||||||
|
--
|
||||||
|
-- gclp 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.
|
||||||
|
--
|
||||||
|
-- gclp 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 gclp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
--
|
||||||
|
with Generic_Line_Parser;
|
||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
package body Parsing_Test is
|
||||||
|
function To_U (X : String) return Unbounded_String
|
||||||
|
renames To_Unbounded_String;
|
||||||
|
|
||||||
|
-- Instantiate the new package
|
||||||
|
package Line_Parser is
|
||||||
|
new Generic_Line_Parser (Config_Data);
|
||||||
|
|
||||||
|
-- ------------------- --
|
||||||
|
-- Parameter Callbacks --
|
||||||
|
-- ------------------- --
|
||||||
|
|
||||||
|
-- X Parameter callbak
|
||||||
|
procedure X_Parameter (Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out Config_Data)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.X := Line_Parser.To_Natural (Value);
|
||||||
|
end X_Parameter;
|
||||||
|
|
||||||
|
-- Y Parameter callbak
|
||||||
|
procedure Y_Parameter (Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out Config_Data)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Y := Line_Parser.To_Natural (Value);
|
||||||
|
end Y_Parameter;
|
||||||
|
|
||||||
|
procedure Z_Parameter (Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out Config_Data)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Z := Line_Parser.To_Float (Value);
|
||||||
|
end Z_Parameter;
|
||||||
|
-- Y Parameter callbak
|
||||||
|
procedure File_Parameter (Name : in Unbounded_String;
|
||||||
|
Value : in Unbounded_String;
|
||||||
|
Result : in out Config_Data)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Result.Filename := Value;
|
||||||
|
end File_Parameter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Param_Spec : Line_Parser.Parameter_Descriptor_Array :=
|
||||||
|
((Name => To_U ("x,X"),
|
||||||
|
Default => <>,
|
||||||
|
If_Missing => Line_Parser.Die,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => X_Parameter'Access),
|
||||||
|
|
||||||
|
(Name => To_U ("y,Y"),
|
||||||
|
Default => <>,
|
||||||
|
If_Missing => Line_Parser.Die,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Y_Parameter'Access),
|
||||||
|
|
||||||
|
(Name => To_U ("z"),
|
||||||
|
Default => To_U ("3.1415"),
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => Z_Parameter'Access),
|
||||||
|
|
||||||
|
(Name => To_U ("filename,file,input"),
|
||||||
|
Default => <>,
|
||||||
|
If_Missing => Line_Parser.Die,
|
||||||
|
Only_Once => True,
|
||||||
|
Callback => File_Parameter'Access));
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Get_Parameters --
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
procedure Get_Parameters (Config : out Config_Data) is
|
||||||
|
begin
|
||||||
|
Line_Parser.Parse_Command_Line (Parameters => Param_Spec,
|
||||||
|
Result => Config);
|
||||||
|
end Get_Parameters;
|
||||||
|
|
||||||
|
end Parsing_Test;
|
@ -0,0 +1,38 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- Generic Command Line Parser (gclp)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2012, Riccardo Bernardini
|
||||||
|
--
|
||||||
|
-- This file is part of gclp.
|
||||||
|
--
|
||||||
|
-- gclp 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.
|
||||||
|
--
|
||||||
|
-- gclp 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 gclp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
package Parsing_Test is
|
||||||
|
-- This is the minimal interface that you need to export to the main
|
||||||
|
-- program: the configuration record type declaration and a procedure
|
||||||
|
-- to initialize it with the command line data.
|
||||||
|
|
||||||
|
type Config_Data is
|
||||||
|
record
|
||||||
|
X : Integer;
|
||||||
|
Y : Integer;
|
||||||
|
Z : Float;
|
||||||
|
Filename : Unbounded_String;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
procedure Get_Parameters (Config : out Config_Data);
|
||||||
|
end Parsing_Test;
|
@ -0,0 +1,35 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- Generic Command Line Parser (gclp)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2012, Riccardo Bernardini
|
||||||
|
--
|
||||||
|
-- This file is part of gclp.
|
||||||
|
--
|
||||||
|
-- gclp 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.
|
||||||
|
--
|
||||||
|
-- gclp 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 gclp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
with Parsing_Test;
|
||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Text_IO; use Ada.Text_IO;
|
||||||
|
|
||||||
|
procedure Test is
|
||||||
|
Config : Parsing_Test.Config_Data;
|
||||||
|
begin
|
||||||
|
Parsing_Test.Get_Parameters (Config);
|
||||||
|
|
||||||
|
Put_Line ("X=" & Integer'Image (Config.X));
|
||||||
|
Put_Line ("Y=" & Integer'Image (Config.Y));
|
||||||
|
Put_Line ("Z=" & Float'Image (Config.Z));
|
||||||
|
Put_Line ("file='" & To_String (Config.Filename) & "'");
|
||||||
|
end Test;
|
@ -0,0 +1,14 @@
|
|||||||
|
with "../gclp.gpr";
|
||||||
|
|
||||||
|
project Test is
|
||||||
|
|
||||||
|
for Object_Dir use "bin";
|
||||||
|
|
||||||
|
package Compiler is
|
||||||
|
for Default_Switches ("ada") use ("-gnat05", "-gnata", "-g");
|
||||||
|
end Compiler;
|
||||||
|
|
||||||
|
for Main use ("test.adb");
|
||||||
|
|
||||||
|
end Test;
|
||||||
|
|
@ -0,0 +1,532 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Strings.Fixed;
|
||||||
|
with Ada.Streams;
|
||||||
|
|
||||||
|
with AWS.Response;
|
||||||
|
with AWS.Status;
|
||||||
|
with AWS.MIME;
|
||||||
|
with AWS.Messages;
|
||||||
|
with AWS.Response.Set;
|
||||||
|
|
||||||
|
with GNAT.IO;
|
||||||
|
with Socket;
|
||||||
|
with HTTP;
|
||||||
|
with GNATCOLL.JSON;
|
||||||
|
with Tokenize;
|
||||||
|
|
||||||
|
with Globals;
|
||||||
|
with Utils;
|
||||||
|
-- build: ctrl+ shift + b
|
||||||
|
-- check file: alt + v
|
||||||
|
|
||||||
|
package body Docker is
|
||||||
|
|
||||||
|
use AWS;
|
||||||
|
use GNAT.IO;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- List containers.
|
||||||
|
--
|
||||||
|
|
||||||
|
function List_Containers (Request : in Status.Data) return Response.Data is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line ("[" & X_Forwarded_User & "] list containers");
|
||||||
|
|
||||||
|
Build_Request :
|
||||||
|
declare
|
||||||
|
Is_Admin : Boolean := Utils.Is_Admin (X_Forwarded_User);
|
||||||
|
begin
|
||||||
|
if Is_Admin then
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("GET /containers/json?size=true&filters={""label"":[""codefirst-usercontainer=true""]} HTTP/1.0" &
|
||||||
|
ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
else
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("GET /containers/json?size=true&filters={""label"":[""" &
|
||||||
|
X_Forwarded_User & "=admin""]} HTTP/1.0" & ASCII.CR &
|
||||||
|
ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
end if;
|
||||||
|
end Build_Request;
|
||||||
|
|
||||||
|
-- Put_Line (To_String (Message));
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
-- Put_Line (To_String (HTTP_Response.Body_Content));
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end List_Containers;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Create container.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Create_Container
|
||||||
|
(Request : in Status.Data; Container_Name : in String)
|
||||||
|
return Response.Data
|
||||||
|
is
|
||||||
|
use GNATCOLL;
|
||||||
|
use Ada.Streams;
|
||||||
|
use Globals;
|
||||||
|
|
||||||
|
Container : JSON.JSON_Value;
|
||||||
|
New_Container : JSON.JSON_Value := JSON.Create_Object;
|
||||||
|
New_Container_Name : Unbounded_String;
|
||||||
|
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line
|
||||||
|
("[" & X_Forwarded_User & "] create container " & Container_Name);
|
||||||
|
|
||||||
|
declare
|
||||||
|
Body_Content : String := HTTP.Extract_Request_Body (Request);
|
||||||
|
New_Body_Content : Unbounded_String;
|
||||||
|
New_Body_Content_Len : Natural;
|
||||||
|
Image_Name : JSON.UTF8_Unbounded_String;
|
||||||
|
Admins : JSON.UTF8_Unbounded_String;
|
||||||
|
Private_Container : Boolean := False;
|
||||||
|
Env_Variables : JSON.JSON_Array;
|
||||||
|
Labels : JSON.JSON_Value := JSON.Create_Object;
|
||||||
|
HostConfig : JSON.JSON_Value := JSON.Create_Object;
|
||||||
|
RestartPolicy : JSON.JSON_Value := JSON.Create_Object;
|
||||||
|
NetworkMode : JSON.UTF8_Unbounded_String;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Container := JSON.Read (Body_Content);
|
||||||
|
|
||||||
|
-- Building new container name;
|
||||||
|
-- Append (New_Container_Name, Container_Name & "-" & X_Forwarded_User);
|
||||||
|
Append (New_Container_Name, Container_Name);
|
||||||
|
|
||||||
|
-- Getting required image name.
|
||||||
|
if not JSON.Has_Field (Container, "Image") then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Image name missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Image_Name := JSON.Get (Container, "Image");
|
||||||
|
|
||||||
|
-- Private container ?
|
||||||
|
if JSON.Has_Field (Container, "Private") then
|
||||||
|
Private_Container := True;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Admins: comma separated list of admins with the syntax "firstname.lastname".
|
||||||
|
if JSON.Has_Field (Container, "Admins") then
|
||||||
|
Admins := JSON.Get (Container, "Admins");
|
||||||
|
end if;
|
||||||
|
|
||||||
|
declare
|
||||||
|
Splitted_Admins : Tokenize.Token_Array :=
|
||||||
|
Tokenize.Split (To_String (Admins), ',');
|
||||||
|
begin
|
||||||
|
Set_Admins:
|
||||||
|
for I in Splitted_Admins'Range loop
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels, To_String (Splitted_Admins (I)), "admin");
|
||||||
|
end loop Set_Admins;
|
||||||
|
end;
|
||||||
|
|
||||||
|
JSON.Set_Field (Labels, X_Forwarded_User, "admin");
|
||||||
|
|
||||||
|
-- Getting optionnal Env values.
|
||||||
|
if JSON.Has_Field (Container, "Env") then
|
||||||
|
Env_Variables := JSON.Get (Container, "Env");
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Configuring network.
|
||||||
|
JSON.Set_Field (RestartPolicy, "Name", "unless-stopped");
|
||||||
|
JSON.Set_Field
|
||||||
|
(RestartPolicy, "MaximumRetryCount", Integer'Value ("0"));
|
||||||
|
JSON.Set_Field (HostConfig, "NetworkMode", Param_DockerNetworkName);
|
||||||
|
JSON.Set_Field (HostConfig, "RestartPolicy", RestartPolicy);
|
||||||
|
JSON.Set_Field (New_Container, "HostConfig", HostConfig);
|
||||||
|
|
||||||
|
-- Building labels.
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels,
|
||||||
|
"traefik.http.routers." & To_String (New_Container_Name) & ".rule",
|
||||||
|
"Host(`" & Param_Hostname & "`) && PathPrefix(`/" &
|
||||||
|
Param_DockerPathPrefix & "/" & To_String (New_Container_Name) &
|
||||||
|
"`)");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels,
|
||||||
|
"traefik.http.routers." & To_String (New_Container_Name) &
|
||||||
|
".entrypoints",
|
||||||
|
"websecure");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels,
|
||||||
|
"traefik.http.routers." & To_String (New_Container_Name) &
|
||||||
|
".tls.certresolver",
|
||||||
|
"letsEncrypt");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels,
|
||||||
|
"traefik.http.middlewares.strip-" &
|
||||||
|
To_String (New_Container_Name) & ".stripprefix.prefixes",
|
||||||
|
"/" & Param_DockerPathPrefix & "/" &
|
||||||
|
To_String (New_Container_Name));
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels,
|
||||||
|
"traefik.http.routers." & To_String (New_Container_Name) &
|
||||||
|
".middlewares",
|
||||||
|
"strip-" & To_String (New_Container_Name) & "@docker");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels, "codefirst-containername", To_String (New_Container_Name));
|
||||||
|
JSON.Set_Field (Labels, "codefirst-user", X_Forwarded_User);
|
||||||
|
JSON.Set_Field (Labels, "codefirst-usercontainer", "true");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels, "traefik.docker.network", Param_DockerNetworkName);
|
||||||
|
|
||||||
|
if Private_Container then
|
||||||
|
JSON.Set_Field (Labels, "codefirst-private", "true");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels, "codefirst-container-endpoint",
|
||||||
|
To_String (New_Container_Name));
|
||||||
|
else
|
||||||
|
JSON.Set_Field (Labels, "traefik.enable", "true");
|
||||||
|
JSON.Set_Field (Labels, "codefirst-private", "false");
|
||||||
|
JSON.Set_Field
|
||||||
|
(Labels, "codefirst-container-endpoint",
|
||||||
|
Param_Scheme & "://" & Param_Hostname & "/" &
|
||||||
|
Param_DockerPathPrefix & "/" & To_String (New_Container_Name));
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Building final new container.
|
||||||
|
JSON.Set_Field (New_Container, "Image", Image_Name);
|
||||||
|
JSON.Set_Field (New_Container, "Labels", Labels);
|
||||||
|
JSON.Set_Field (New_Container, "Env", Env_Variables);
|
||||||
|
|
||||||
|
New_Body_Content := To_Unbounded_String (JSON.Write (New_Container));
|
||||||
|
New_Body_Content_Len := Length (New_Body_Content);
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("POST /containers/create?name=" &
|
||||||
|
To_String (New_Container_Name) & " HTTP/1.0" & ASCII.CR &
|
||||||
|
ASCII.LF & "Content-Type: application/json" & ASCII.CR &
|
||||||
|
ASCII.LF & "Host: docker" & ASCII.CR & ASCII.LF &
|
||||||
|
"Content-length: " & New_Body_Content_Len'Img & ASCII.CR &
|
||||||
|
ASCII.LF & "Connection: close" & ASCII.CR & ASCII.LF & ASCII.CR &
|
||||||
|
ASCII.LF & To_String (New_Body_Content) & ASCII.CR & ASCII.LF &
|
||||||
|
"EOF" & ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Create_Container;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Start container.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Start_Container
|
||||||
|
(Request : in Status.Data; Container_Id : in String) return Response.Data
|
||||||
|
is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line ("[" & X_Forwarded_User & "] start container " & Container_Id);
|
||||||
|
|
||||||
|
if (Container_Id'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Container ID missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("POST /containers/" & Container_Id & "/start HTTP/1.0" & ASCII.CR &
|
||||||
|
ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Start_Container;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Stop container.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Stop_Container
|
||||||
|
(Request : in Status.Data; Container_Id : in String) return Response.Data
|
||||||
|
is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line ("[" & X_Forwarded_User & "] stop container " & Container_Id);
|
||||||
|
|
||||||
|
if (Container_Id'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Container ID missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("POST /containers/" & Container_Id & "/stop?t=10 HTTP/1.0" &
|
||||||
|
ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Stop_Container;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Inspect container.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Inspect_Container
|
||||||
|
(Request : in Status.Data; Container_Id : in String) return Response.Data
|
||||||
|
is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line
|
||||||
|
("[" & X_Forwarded_User & "] inspect container " & Container_Id);
|
||||||
|
|
||||||
|
if (Container_Id'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Container ID missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("GET /containers/" & Container_Id & "/json HTTP/1.0" & ASCII.CR &
|
||||||
|
ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Inspect_Container;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Get container log.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Get_Container_Log
|
||||||
|
(Request : in Status.Data; Container_Id : in String) return Response.Data
|
||||||
|
is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line
|
||||||
|
("[" & X_Forwarded_User & "] get container log " & Container_Id);
|
||||||
|
|
||||||
|
if (Container_Id'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Container ID missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("GET /containers/" & Container_Id &
|
||||||
|
"/logs?stdout=true&stderr=true HTTP/1.0" & ASCII.CR & ASCII.LF &
|
||||||
|
ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Get_Container_Log;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Remove container.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Remove_Container
|
||||||
|
(Request : in Status.Data; Container_Id : in String) return Response.Data
|
||||||
|
is
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line ("[" & X_Forwarded_User & "] remove container " & Container_Id);
|
||||||
|
|
||||||
|
if (Container_Id'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Container ID missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("DELETE /containers/" & Container_Id &
|
||||||
|
"?v=true&force=true HTTP/1.0" & ASCII.CR & ASCII.LF & ASCII.CR &
|
||||||
|
ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Remove_Container;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Create image.
|
||||||
|
--
|
||||||
|
|
||||||
|
function Create_Image
|
||||||
|
(Request : in Status.Data; Image_Name : in String) return Response.Data
|
||||||
|
is
|
||||||
|
New_Image_Name : Unbounded_String := To_Unbounded_String (Image_Name);
|
||||||
|
Message : Unbounded_String;
|
||||||
|
Socket_Response_Vec : Socket.Socket_Response_Vectors.Vector;
|
||||||
|
HTTP_Response : HTTP.Response;
|
||||||
|
X_Forwarded_User : String := HTTP.Get_X_Forwarded_User (Request);
|
||||||
|
Image_Has_Tag : Boolean := False;
|
||||||
|
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
|
||||||
|
Put_Line ("[" & X_Forwarded_User & "] create image from " & Image_Name);
|
||||||
|
|
||||||
|
for i in Image_Name'Range loop
|
||||||
|
if (Image_Name (i) = ':') then
|
||||||
|
Image_Has_Tag := True;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
if not Image_Has_Tag then
|
||||||
|
Append (New_Image_Name, ":latest");
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if (Image_Name'Length = 0) then
|
||||||
|
return
|
||||||
|
Response.Acknowledge
|
||||||
|
(Messages.S400, "Image name missing.", MIME.Text_Plain);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Message :=
|
||||||
|
To_Unbounded_String
|
||||||
|
("POST /images/create?fromImage=" & To_String (New_Image_Name) &
|
||||||
|
" HTTP/1.0" & ASCII.CR & ASCII.LF &
|
||||||
|
"Content-Type: application/tar" & ASCII.CR & ASCII.LF & ASCII.CR &
|
||||||
|
ASCII.LF & ASCII.CR & ASCII.LF);
|
||||||
|
|
||||||
|
Socket_Response_Vec := Socket.Send_To_Socket (To_String (Message));
|
||||||
|
HTTP_Response := HTTP.From_Socket_Response (Socket_Response_Vec);
|
||||||
|
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Application_JSON,
|
||||||
|
Message_Body => To_String (HTTP_Response.Body_Content),
|
||||||
|
Status_Code => HTTP_Response.Status_Code);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header (Resp, "access-control-allow-origin", "* ");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
|
||||||
|
end Create_Image;
|
||||||
|
|
||||||
|
end Docker;
|
@ -0,0 +1,24 @@
|
|||||||
|
with AWS.Response;
|
||||||
|
with AWS.Status;
|
||||||
|
|
||||||
|
package Docker is
|
||||||
|
|
||||||
|
use AWS;
|
||||||
|
|
||||||
|
function List_Containers (Request : in Status.Data) return Response.Data;
|
||||||
|
|
||||||
|
function Start_Container (Request : in Status.Data; Container_Id : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Stop_Container (Request : in Status.Data; Container_Id : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Create_Container (Request : in Status.Data; Container_Name : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Remove_Container (Request : in Status.Data; Container_Id : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Inspect_Container (Request : in Status.Data; Container_Id : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Get_Container_Log (Request : in Status.Data; Container_Id : in String) return Response.Data;
|
||||||
|
|
||||||
|
function Create_Image (Request : in Status.Data; Image_Name : in String) return Response.Data;
|
||||||
|
|
||||||
|
end Docker;
|
@ -0,0 +1,168 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Strings.Bounded; use Ada.Strings.Bounded;
|
||||||
|
|
||||||
|
with AWS.Messages;
|
||||||
|
with AWS.MIME;
|
||||||
|
with AWS.Status;
|
||||||
|
with AWS.Response.Set;
|
||||||
|
|
||||||
|
with GNAT.Regpat;
|
||||||
|
with GNAT.IO;
|
||||||
|
|
||||||
|
with Docker;
|
||||||
|
with Types;
|
||||||
|
|
||||||
|
package body Dockerproxy.Callbacks is
|
||||||
|
|
||||||
|
-- Container names are max 128 characters.
|
||||||
|
|
||||||
|
use Types.Container_Name_Str;
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- Default --
|
||||||
|
-------------
|
||||||
|
|
||||||
|
function Default (Request : in Status.Data) return Response.Data is
|
||||||
|
|
||||||
|
use AWS.Status;
|
||||||
|
use GNAT.Regpat;
|
||||||
|
use GNAT.IO;
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
URI : constant String := Status.URI (Request);
|
||||||
|
Method : constant Request_Method := Status.Method (Request);
|
||||||
|
|
||||||
|
Create_Container_Re : Pattern_Matcher (100);
|
||||||
|
Create_Container_Matches : Match_Array (1 .. 1);
|
||||||
|
Remove_Container_Re : Pattern_Matcher (100);
|
||||||
|
Remove_Container_Matches : Match_Array (1 .. 1);
|
||||||
|
List_Containers_Re : Pattern_Matcher (100);
|
||||||
|
List_Containers_Matches : Match_Array (1 .. 1);
|
||||||
|
Get_Container_Log_Re : Pattern_Matcher (100);
|
||||||
|
Get_Container_Log_Matches : Match_Array (1 .. 1);
|
||||||
|
Inspect_Container_Re : Pattern_Matcher (100);
|
||||||
|
Inspect_Container_Matches : Match_Array (1 .. 1);
|
||||||
|
Start_Container_Re : Pattern_Matcher (100);
|
||||||
|
Start_Container_Matches : Match_Array (1 .. 1);
|
||||||
|
Stop_Container_Re : Pattern_Matcher (100);
|
||||||
|
Stop_Container_Matches : Match_Array (1 .. 1);
|
||||||
|
Create_Image_Re : Pattern_Matcher (100);
|
||||||
|
Create_Image_Matches : Match_Array (1 .. 1);
|
||||||
|
|
||||||
|
-- Container name or ID, image name...
|
||||||
|
Request_Variable_Part : Bounded_String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
Compile (Create_Container_Re, "/containers/create/(.+)");
|
||||||
|
Compile (Remove_Container_Re, "/containers/(.+)");
|
||||||
|
Compile (List_Containers_Re, "(/containers/json)");
|
||||||
|
Compile (Get_Container_Log_Re, "/containers/(.+)/logs");
|
||||||
|
Compile (Inspect_Container_Re, "/containers/(.+)/json");
|
||||||
|
Compile (Start_Container_Re, "/containers/(.+)/start");
|
||||||
|
Compile (Stop_Container_Re, "/containers/(.+)/stop");
|
||||||
|
Compile (Create_Image_Re, "(/images/create)");
|
||||||
|
|
||||||
|
Match (Create_Container_Re, URI, Create_Container_Matches);
|
||||||
|
Match (Remove_Container_Re, URI, Remove_Container_Matches);
|
||||||
|
Match (List_Containers_Re, URI, List_Containers_Matches);
|
||||||
|
Match (Get_Container_Log_Re, URI, Get_Container_Log_Matches);
|
||||||
|
Match (Inspect_Container_Re, URI, Inspect_Container_Matches);
|
||||||
|
Match (Start_Container_Re, URI, Start_Container_Matches);
|
||||||
|
Match (Stop_Container_Re, URI, Stop_Container_Matches);
|
||||||
|
Match (Create_Image_Re, URI, Create_Image_Matches);
|
||||||
|
|
||||||
|
if
|
||||||
|
(Create_Container_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(POST))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Create_Container_Matches (1).First .. Create_Container_Matches (1).Last));
|
||||||
|
return Docker.Create_Container (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Remove_Container_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(DELETE))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Remove_Container_Matches (1).First .. Remove_Container_Matches (1).Last));
|
||||||
|
return Docker.Remove_Container (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(List_Containers_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(GET))
|
||||||
|
then
|
||||||
|
|
||||||
|
return Docker.List_Containers (Request);
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Get_Container_Log_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(GET))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Get_Container_Log_Matches (1).First .. Get_Container_Log_Matches (1).Last));
|
||||||
|
return Docker.Get_Container_Log (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Inspect_Container_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(GET))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Inspect_Container_Matches (1).First .. Inspect_Container_Matches (1).Last));
|
||||||
|
return Docker.Inspect_Container (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Start_Container_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(POST))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Start_Container_Matches (1).First .. Start_Container_Matches (1).Last));
|
||||||
|
return Docker.Start_Container (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Stop_Container_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(POST))
|
||||||
|
then
|
||||||
|
|
||||||
|
Set_Bounded_String (Request_Variable_Part, URI (Stop_Container_Matches (1).First .. Stop_Container_Matches (1).Last));
|
||||||
|
return Docker.Stop_Container (Request, To_String (Request_Variable_Part));
|
||||||
|
|
||||||
|
elsif
|
||||||
|
(Create_Image_Matches (1) /= No_Match and
|
||||||
|
Method = Request_Method'(POST))
|
||||||
|
then
|
||||||
|
|
||||||
|
declare
|
||||||
|
Image_Name : String := AWS.Status.Parameter (Request, "fromImage");
|
||||||
|
begin
|
||||||
|
return Docker.Create_Image (Request, Image_Name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
elsif (Method = Request_Method'(OPTIONS)) then
|
||||||
|
|
||||||
|
declare
|
||||||
|
Resp : Response.Data;
|
||||||
|
begin
|
||||||
|
Resp :=
|
||||||
|
Response.Build
|
||||||
|
(Content_Type => MIME.Text_Plain, Message_Body => "No content",
|
||||||
|
Status_Code => Messages.S204);
|
||||||
|
|
||||||
|
AWS.Response.Set.Add_Header
|
||||||
|
(Resp, "Access-Control-Allow-Origin", "* ");
|
||||||
|
AWS.Response.Set.Add_Header
|
||||||
|
(Resp, "Access-Control-Allow-Methods",
|
||||||
|
"GET, OPTIONS, POST, PUT, DELETE");
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
return Response.Acknowledge (Messages.S404);
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end Default;
|
||||||
|
|
||||||
|
end Dockerproxy.Callbacks;
|
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
with AWS.Response;
|
||||||
|
with AWS.Status;
|
||||||
|
|
||||||
|
package Dockerproxy.Callbacks is
|
||||||
|
|
||||||
|
use AWS;
|
||||||
|
|
||||||
|
function Default (Request : in Status.Data) return Response.Data;
|
||||||
|
|
||||||
|
end Dockerproxy.Callbacks;
|
@ -0,0 +1,105 @@
|
|||||||
|
with GNAT.IO; use GNAT.IO;
|
||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
with AWS.Config.Set;
|
||||||
|
with AWS.Server;
|
||||||
|
|
||||||
|
with Dockerproxy.Callbacks;
|
||||||
|
|
||||||
|
with Generic_Line_Parser;
|
||||||
|
|
||||||
|
with Parameters;
|
||||||
|
|
||||||
|
with Globals;
|
||||||
|
|
||||||
|
procedure Dockerproxy.Main is
|
||||||
|
use AWS;
|
||||||
|
|
||||||
|
Web_Server : Server.HTTP;
|
||||||
|
Web_Config : Config.Object;
|
||||||
|
|
||||||
|
package Line_Parser is new Generic_Line_Parser (Parameters.User_Parameters);
|
||||||
|
|
||||||
|
use type Line_Parser.Missing_Action;
|
||||||
|
|
||||||
|
Descriptors : constant Line_Parser.Parameter_Descriptor_Array :=
|
||||||
|
[(Name => To_Unbounded_String ("--hostname"),
|
||||||
|
Default => To_Unbounded_String ("localhost"), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Callback => Parameters.Set_Hostname'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--scheme"),
|
||||||
|
Default => To_Unbounded_String ("http"), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Callback => Parameters.Set_Scheme'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--dockerpathprefix"),
|
||||||
|
Default => To_Unbounded_String ("containers"), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Callback => Parameters.Set_DockerPathPrefix'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--dockernetworkname"),
|
||||||
|
Default => To_Unbounded_String ("run_net"), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Callback => Parameters.Set_DockerNetworkName'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--maxallowedcontainers"),
|
||||||
|
Default => To_Unbounded_String ("3"), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Use_Default,
|
||||||
|
Callback => Parameters.Set_MaxAllowedContainers'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--devel,-d"),
|
||||||
|
Default => To_Unbounded_String (""), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Ignore,
|
||||||
|
Callback => Parameters.Set_Devel'Access),
|
||||||
|
|
||||||
|
(Name => To_Unbounded_String ("--admins"),
|
||||||
|
Default => To_Unbounded_String (""), Only_Once => True,
|
||||||
|
If_Missing => Line_Parser.Ignore,
|
||||||
|
Callback => Parameters.Set_Admins'Access)];
|
||||||
|
|
||||||
|
Param : Parameters.User_Parameters;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Command line parameters
|
||||||
|
|
||||||
|
Line_Parser.Parse_Command_Line (Parameters => Descriptors, Result => Param);
|
||||||
|
|
||||||
|
Globals.Param_Devel := Param.Devel;
|
||||||
|
Globals.Param_Admins := Param.Admins;
|
||||||
|
Globals.Param_DockerNetworkName := Param.DockerNetworkName;
|
||||||
|
Globals.Param_DockerPathPrefix := Param.DockerPathPrefix;
|
||||||
|
Globals.Param_Hostname := Param.Hostname;
|
||||||
|
Globals.Param_MaxAllowedContainers := Param.MaxAllowedContainers;
|
||||||
|
Globals.Param_Scheme := Param.Scheme;
|
||||||
|
|
||||||
|
Put_Line ("--devel => " & To_String (Param.Devel));
|
||||||
|
Put_Line ("--hostname => " & To_String (Param.Hostname));
|
||||||
|
Put_Line ("--scheme => " & To_String (Param.Scheme));
|
||||||
|
Put_Line ("--dockerpathprefix => " & To_String (Param.DockerPathPrefix));
|
||||||
|
Put_Line ("--dockernetworkname => " & To_String (Param.DockerNetworkName));
|
||||||
|
Put_Line ("--maxallowedcontainers => " & Param.MaxAllowedContainers'Img);
|
||||||
|
|
||||||
|
for admin of Param.Admins loop
|
||||||
|
Put_Line ("-admin: " & To_String (admin));
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
-- Setup
|
||||||
|
|
||||||
|
Config.Set.Server_Host (Web_Config, Host);
|
||||||
|
Config.Set.Server_Port (Web_Config, Port);
|
||||||
|
|
||||||
|
-- Start the server
|
||||||
|
|
||||||
|
Server.Start (Web_Server, Callbacks.Default'Access, Web_Config);
|
||||||
|
|
||||||
|
-- Wait for the Q key
|
||||||
|
|
||||||
|
Server.Wait (Server.Forever);
|
||||||
|
-- Server.Wait (Server.Q_Key_Pressed);
|
||||||
|
|
||||||
|
-- Stop the server
|
||||||
|
|
||||||
|
Server.Shutdown (Web_Server);
|
||||||
|
end Dockerproxy.Main;
|
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
package Dockerproxy is
|
||||||
|
pragma Pure;
|
||||||
|
|
||||||
|
Host : constant String := "0.0.0.0";
|
||||||
|
Port : constant := 8080;
|
||||||
|
|
||||||
|
end Dockerproxy;
|
@ -0,0 +1,18 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
with Parameters;
|
||||||
|
with Types;
|
||||||
|
|
||||||
|
package Globals is
|
||||||
|
|
||||||
|
use Types;
|
||||||
|
|
||||||
|
Param_Devel : Unbounded_String;
|
||||||
|
Param_Admins : Parameters.Admins_Vector.Vector;
|
||||||
|
Param_Hostname : Unbounded_String;
|
||||||
|
Param_Scheme : Unbounded_String;
|
||||||
|
Param_DockerPathPrefix : Unbounded_String;
|
||||||
|
Param_DockerNetworkName : Unbounded_String;
|
||||||
|
Param_MaxAllowedContainers : MaxAllowedContainers_Type;
|
||||||
|
|
||||||
|
end Globals;
|
@ -0,0 +1,142 @@
|
|||||||
|
|
||||||
|
package body HTTP.Status is
|
||||||
|
|
||||||
|
function AWS_StatusCode_From_String
|
||||||
|
(StatusCode_String : in String) return AWS.Messages.Status_Code
|
||||||
|
is
|
||||||
|
use AWS.Messages;
|
||||||
|
|
||||||
|
Status : AWS.Messages.Status_Code;
|
||||||
|
begin
|
||||||
|
|
||||||
|
if StatusCode_String = "100" then
|
||||||
|
Status := S100;
|
||||||
|
elsif StatusCode_String = "101" then
|
||||||
|
Status := S101;
|
||||||
|
elsif StatusCode_String = "102" then
|
||||||
|
Status := S102;
|
||||||
|
elsif StatusCode_String = "200" then
|
||||||
|
Status := S200;
|
||||||
|
elsif StatusCode_String = "201" then
|
||||||
|
Status := S201;
|
||||||
|
elsif StatusCode_String = "202" then
|
||||||
|
Status := S202;
|
||||||
|
elsif StatusCode_String = "203" then
|
||||||
|
Status := S203;
|
||||||
|
elsif StatusCode_String = "204" then
|
||||||
|
Status := S204;
|
||||||
|
elsif StatusCode_String = "205" then
|
||||||
|
Status := S205;
|
||||||
|
elsif StatusCode_String = "206" then
|
||||||
|
Status := S206;
|
||||||
|
elsif StatusCode_String = "207" then
|
||||||
|
Status := S207;
|
||||||
|
elsif StatusCode_String = "208" then
|
||||||
|
Status := S208;
|
||||||
|
elsif StatusCode_String = "226" then
|
||||||
|
Status := S226;
|
||||||
|
elsif StatusCode_String = "300" then
|
||||||
|
Status := S300;
|
||||||
|
elsif StatusCode_String = "301" then
|
||||||
|
Status := S301;
|
||||||
|
elsif StatusCode_String = "302" then
|
||||||
|
Status := S302;
|
||||||
|
elsif StatusCode_String = "303" then
|
||||||
|
Status := S303;
|
||||||
|
elsif StatusCode_String = "304" then
|
||||||
|
Status := S304;
|
||||||
|
elsif StatusCode_String = "305" then
|
||||||
|
Status := S305;
|
||||||
|
elsif StatusCode_String = "306" then
|
||||||
|
Status := S306;
|
||||||
|
elsif StatusCode_String = "307" then
|
||||||
|
Status := S307;
|
||||||
|
elsif StatusCode_String = "308" then
|
||||||
|
Status := S308;
|
||||||
|
elsif StatusCode_String = "400" then
|
||||||
|
Status := S400;
|
||||||
|
elsif StatusCode_String = "401" then
|
||||||
|
Status := S401;
|
||||||
|
elsif StatusCode_String = "402" then
|
||||||
|
Status := S402;
|
||||||
|
elsif StatusCode_String = "403" then
|
||||||
|
Status := S403;
|
||||||
|
elsif StatusCode_String = "404" then
|
||||||
|
Status := S404;
|
||||||
|
elsif StatusCode_String = "405" then
|
||||||
|
Status := S405;
|
||||||
|
elsif StatusCode_String = "406" then
|
||||||
|
Status := S406;
|
||||||
|
elsif StatusCode_String = "407" then
|
||||||
|
Status := S407;
|
||||||
|
elsif StatusCode_String = "408" then
|
||||||
|
Status := S408;
|
||||||
|
elsif StatusCode_String = "409" then
|
||||||
|
Status := S409;
|
||||||
|
elsif StatusCode_String = "410" then
|
||||||
|
Status := S410;
|
||||||
|
elsif StatusCode_String = "411" then
|
||||||
|
Status := S411;
|
||||||
|
elsif StatusCode_String = "412" then
|
||||||
|
Status := S412;
|
||||||
|
elsif StatusCode_String = "413" then
|
||||||
|
Status := S413;
|
||||||
|
elsif StatusCode_String = "414" then
|
||||||
|
Status := S414;
|
||||||
|
elsif StatusCode_String = "415" then
|
||||||
|
Status := S415;
|
||||||
|
elsif StatusCode_String = "416" then
|
||||||
|
Status := S416;
|
||||||
|
elsif StatusCode_String = "417" then
|
||||||
|
Status := S417;
|
||||||
|
elsif StatusCode_String = "418" then
|
||||||
|
Status := S418;
|
||||||
|
elsif StatusCode_String = "421" then
|
||||||
|
Status := S421;
|
||||||
|
elsif StatusCode_String = "422" then
|
||||||
|
Status := S422;
|
||||||
|
elsif StatusCode_String = "423" then
|
||||||
|
Status := S423;
|
||||||
|
elsif StatusCode_String = "424" then
|
||||||
|
Status := S424;
|
||||||
|
elsif StatusCode_String = "425" then
|
||||||
|
Status := S425;
|
||||||
|
elsif StatusCode_String = "426" then
|
||||||
|
Status := S426;
|
||||||
|
elsif StatusCode_String = "428" then
|
||||||
|
Status := S428;
|
||||||
|
elsif StatusCode_String = "429" then
|
||||||
|
Status := S429;
|
||||||
|
elsif StatusCode_String = "431" then
|
||||||
|
Status := S431;
|
||||||
|
elsif StatusCode_String = "451" then
|
||||||
|
Status := S451;
|
||||||
|
elsif StatusCode_String = "500" then
|
||||||
|
Status := S500;
|
||||||
|
elsif StatusCode_String = "501" then
|
||||||
|
Status := S501;
|
||||||
|
elsif StatusCode_String = "502" then
|
||||||
|
Status := S502;
|
||||||
|
elsif StatusCode_String = "503" then
|
||||||
|
Status := S503;
|
||||||
|
elsif StatusCode_String = "504" then
|
||||||
|
Status := S504;
|
||||||
|
elsif StatusCode_String = "505" then
|
||||||
|
Status := S505;
|
||||||
|
elsif StatusCode_String = "506" then
|
||||||
|
Status := S506;
|
||||||
|
elsif StatusCode_String = "507" then
|
||||||
|
Status := S507;
|
||||||
|
elsif StatusCode_String = "508" then
|
||||||
|
Status := S508;
|
||||||
|
elsif StatusCode_String = "510" then
|
||||||
|
Status := S510;
|
||||||
|
elsif StatusCode_String = "511" then
|
||||||
|
Status := S511;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
end AWS_StatusCode_From_String;
|
||||||
|
|
||||||
|
end HTTP.Status;
|
@ -0,0 +1,12 @@
|
|||||||
|
with AWS.Messages;
|
||||||
|
|
||||||
|
package HTTP.Status is
|
||||||
|
|
||||||
|
function AWS_StatusCode_From_String
|
||||||
|
(StatusCode_String : in String)
|
||||||
|
return AWS.Messages.Status_Code with
|
||||||
|
Pre => StatusCode_String'Length > 0,
|
||||||
|
Post =>
|
||||||
|
AWS_StatusCode_From_String'Result in AWS.Messages.Status_Code;
|
||||||
|
|
||||||
|
end HTTP.Status;
|
@ -0,0 +1,158 @@
|
|||||||
|
|
||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Strings.Maps;
|
||||||
|
|
||||||
|
with AWS.Headers;
|
||||||
|
with AWS.Status;
|
||||||
|
|
||||||
|
with Tokenize;
|
||||||
|
|
||||||
|
with GNAT.IO; use GNAT.IO;
|
||||||
|
use type Ada.Strings.Maps.Character_Set;
|
||||||
|
with Ada.Streams; use Ada.Streams;
|
||||||
|
use type Ada.Streams.Stream_Element_Count;
|
||||||
|
|
||||||
|
with HTTP.Status;
|
||||||
|
with Globals;
|
||||||
|
|
||||||
|
package body HTTP is
|
||||||
|
|
||||||
|
function From_Socket_Response
|
||||||
|
(Socket_Response_Vec : in Socket.Socket_Response_Vectors.Vector) return Response
|
||||||
|
is
|
||||||
|
HTTP_Response : Response;
|
||||||
|
Body_Reached : Boolean := False;
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Building the HTTP response from the socket response.
|
||||||
|
for I in
|
||||||
|
Socket_Response_Vec.First_Index .. Socket_Response_Vec.Last_Index
|
||||||
|
loop
|
||||||
|
|
||||||
|
declare
|
||||||
|
Current_Line : Unbounded_String;
|
||||||
|
Current_Line_Len : Natural;
|
||||||
|
Header_Separator_Index : Natural;
|
||||||
|
Status_Code_String : String (1 .. 3);
|
||||||
|
begin
|
||||||
|
|
||||||
|
Current_Line := Socket_Response_Vec (I);
|
||||||
|
Current_Line_Len := Length (Current_Line);
|
||||||
|
Header_Separator_Index := Index (Current_Line, ":");
|
||||||
|
|
||||||
|
-- Put_Line (To_String (Current_Line));
|
||||||
|
-- Put_Line (Current_Line_Len'Img);
|
||||||
|
|
||||||
|
-- First line is the HTTP status like: HTTP/1.0 200 OK
|
||||||
|
if I = 0 then
|
||||||
|
|
||||||
|
-- Put_Line ("HTTP status reached");
|
||||||
|
|
||||||
|
declare
|
||||||
|
Splitted_HTTP_Status : Tokenize.Token_Array :=
|
||||||
|
Tokenize.Split (To_String (Current_Line));
|
||||||
|
begin
|
||||||
|
Status_Code_String := To_String (Splitted_HTTP_Status (2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
HTTP_Response.Status_Code := HTTP.Status.AWS_StatusCode_From_String
|
||||||
|
(Status_Code_String);
|
||||||
|
|
||||||
|
elsif Current_Line_Len = 0 then
|
||||||
|
|
||||||
|
-- Put_Line ("Body reached");
|
||||||
|
Body_Reached := True;
|
||||||
|
|
||||||
|
elsif Body_Reached then
|
||||||
|
|
||||||
|
-- Put_Line ("Body");
|
||||||
|
Ada.Strings.Unbounded.Append
|
||||||
|
(HTTP_Response.Body_Content, Current_Line);
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Put_Line ("Headers reached");
|
||||||
|
|
||||||
|
declare
|
||||||
|
Header_Key :
|
||||||
|
String (1 .. (Header_Separator_Index - 1));
|
||||||
|
Header_Value :
|
||||||
|
String
|
||||||
|
(Header_Separator_Index .. (Current_Line_Len));
|
||||||
|
begin
|
||||||
|
Header_Key :=
|
||||||
|
To_String (Current_Line)
|
||||||
|
(1 .. (Header_Separator_Index - 1));
|
||||||
|
Header_Value :=
|
||||||
|
To_String (Current_Line)
|
||||||
|
(Header_Separator_Index .. (Current_Line_Len));
|
||||||
|
|
||||||
|
-- Put_Line ("Header key " & Header_Key);
|
||||||
|
-- Put_Line ("Header value " & Header_Value);
|
||||||
|
end;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return HTTP_Response;
|
||||||
|
|
||||||
|
end From_Socket_Response;
|
||||||
|
|
||||||
|
function Get_X_Forwarded_User (Request : in AWS.Status.Data) return String
|
||||||
|
is
|
||||||
|
Headers : AWS.Headers.List;
|
||||||
|
Separators : Ada.Strings.Maps.Character_Set :=
|
||||||
|
Ada.Strings.Maps.Null_Set;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Headers := AWS.Status.Header (Request);
|
||||||
|
Separators := Ada.Strings.Maps.To_Set ("@.");
|
||||||
|
|
||||||
|
if Length (Globals.Param_Devel) /= 0 then
|
||||||
|
return To_String (Globals.Param_Devel);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
declare
|
||||||
|
-- X-Forwarded-User contains the user email coming from codefirst auth proxy or any string coming from drone.
|
||||||
|
X_Header : String :=
|
||||||
|
AWS.Headers.Get_Values (Headers, "X-Forwarded-User");
|
||||||
|
Splitted_Email : Tokenize.Token_Array :=
|
||||||
|
Tokenize.Split (X_Header, Separators, True);
|
||||||
|
Final_X_Header : Unbounded_String;
|
||||||
|
begin
|
||||||
|
if X_Header'Length = 0 then
|
||||||
|
return "";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Splitted_Email := Tokenize.Split (X_Header, Separators, True);
|
||||||
|
|
||||||
|
Append (Final_X_Header, Splitted_Email (1));
|
||||||
|
if Splitted_Email'Length > 1 then
|
||||||
|
Append (Final_X_Header, Splitted_Email (2));
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return To_String (Final_X_Header);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end Get_X_Forwarded_User;
|
||||||
|
|
||||||
|
function Extract_Request_Body (Request : in AWS.Status.Data) return String
|
||||||
|
is
|
||||||
|
Offset : Stream_Element_Count;
|
||||||
|
Data : Stream_Element_Array (1 .. 256);
|
||||||
|
Body_Content : Unbounded_String;
|
||||||
|
begin
|
||||||
|
loop
|
||||||
|
AWS.Status.Read_Body (Request, Data, Offset);
|
||||||
|
exit when Offset = 0;
|
||||||
|
|
||||||
|
for I in 1 .. Offset loop
|
||||||
|
Append (Body_Content, Character'Val (Data (I)));
|
||||||
|
end loop;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return To_String (Body_Content);
|
||||||
|
end Extract_Request_Body;
|
||||||
|
|
||||||
|
end HTTP;
|
@ -0,0 +1,27 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
with AWS.Messages;
|
||||||
|
with AWS.Status;
|
||||||
|
|
||||||
|
with Socket;
|
||||||
|
|
||||||
|
package HTTP is
|
||||||
|
|
||||||
|
type Response is record
|
||||||
|
Status_Code : AWS.Messages.Status_Code;
|
||||||
|
Body_Content : Unbounded_String;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
function Extract_Request_Body
|
||||||
|
(Request : in AWS.Status.Data) return String with
|
||||||
|
Pre => AWS.Status.Content_Type (Request) /= "0";
|
||||||
|
|
||||||
|
function From_Socket_Response
|
||||||
|
(Socket_Response_Vec : in Socket.Socket_Response_Vectors.Vector)
|
||||||
|
return Response;
|
||||||
|
|
||||||
|
function Get_X_Forwarded_User
|
||||||
|
(Request : in AWS.Status.Data) return String with
|
||||||
|
Post => Get_X_Forwarded_User'Result'Length /= 0;
|
||||||
|
|
||||||
|
end HTTP;
|
@ -0,0 +1,105 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
with Tokenize;
|
||||||
|
|
||||||
|
package body Parameters is
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Admins.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_Admins
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
declare
|
||||||
|
Splitted_Admins : constant Tokenize.Token_Array :=
|
||||||
|
Tokenize.Split (To_String (Value), ',');
|
||||||
|
begin
|
||||||
|
for i in Splitted_Admins'Range loop
|
||||||
|
Result.Admins.Append (Splitted_Admins (i));
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
end Set_Admins;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Devel.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_Devel
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.Devel := Value;
|
||||||
|
end Set_Devel;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Hostname.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_Hostname
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.Hostname := Value;
|
||||||
|
end Set_Hostname;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Scheme.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_Scheme
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.Scheme := Value;
|
||||||
|
end Set_Scheme;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Docker path prefix.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_DockerPathPrefix
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.DockerPathPrefix := Value;
|
||||||
|
end Set_DockerPathPrefix;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Docker network name.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_DockerNetworkName
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.DockerNetworkName := Value;
|
||||||
|
end Set_DockerNetworkName;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Max containers.
|
||||||
|
--
|
||||||
|
|
||||||
|
procedure Set_MaxAllowedContainers
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters)
|
||||||
|
is
|
||||||
|
pragma Unreferenced (Name);
|
||||||
|
begin
|
||||||
|
Result.MaxAllowedContainers := Natural'Value (To_String (value));
|
||||||
|
end Set_MaxAllowedContainers;
|
||||||
|
|
||||||
|
end Parameters;
|
@ -0,0 +1,51 @@
|
|||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
with Ada.Containers.Vectors;
|
||||||
|
with Types;
|
||||||
|
|
||||||
|
package Parameters is
|
||||||
|
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
use Types;
|
||||||
|
|
||||||
|
package Admins_Vector is new Ada.Containers.Vectors
|
||||||
|
(Index_Type => Natural, Element_Type => Unbounded_String);
|
||||||
|
|
||||||
|
type User_Parameters is record
|
||||||
|
Devel : Unbounded_String;
|
||||||
|
Hostname : Unbounded_String;
|
||||||
|
Admins : Admins_Vector.Vector;
|
||||||
|
Scheme : Unbounded_String;
|
||||||
|
DockerPathPrefix : Unbounded_String;
|
||||||
|
DockerNetworkName : Unbounded_String;
|
||||||
|
MaxAllowedContainers : MaxAllowedContainers_Type;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
procedure Set_Admins
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Devel
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Hostname
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_Scheme
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_DockerPathPrefix
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_DockerNetworkName
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
procedure Set_MaxAllowedContainers
|
||||||
|
(Name : in Unbounded_String; Value : in Unbounded_String;
|
||||||
|
Result : in out User_Parameters);
|
||||||
|
|
||||||
|
end Parameters;
|
@ -0,0 +1,82 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Containers.Vectors;
|
||||||
|
with Ada.Streams;
|
||||||
|
use type Ada.Streams.Stream_Element_Count;
|
||||||
|
|
||||||
|
with GNAT.IO;
|
||||||
|
with GNAT.Sockets;
|
||||||
|
|
||||||
|
package body Socket is
|
||||||
|
|
||||||
|
function Send_To_Socket
|
||||||
|
(Message : in String) return Socket_Response_Vectors.Vector
|
||||||
|
is
|
||||||
|
use Socket_Response_Vectors;
|
||||||
|
use GNAT.IO;
|
||||||
|
use GNAT.Sockets;
|
||||||
|
use Ada.Streams;
|
||||||
|
|
||||||
|
Client : Socket_Type;
|
||||||
|
Channel : Stream_Access;
|
||||||
|
Offset : Stream_Element_Count;
|
||||||
|
Data : Stream_Element_Array (1 .. 256);
|
||||||
|
|
||||||
|
Socket_Response_Vec : Socket_Response_Vectors.Vector;
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Connect to socket.
|
||||||
|
Initialize;
|
||||||
|
Create_Socket (Socket => Client, Family => Family_Unix);
|
||||||
|
Connect_Socket
|
||||||
|
(Socket => Client,
|
||||||
|
Server =>
|
||||||
|
(Family => Family_Unix,
|
||||||
|
Name => To_Unbounded_String ("/var/run/docker.sock")));
|
||||||
|
|
||||||
|
Channel := Stream (Client);
|
||||||
|
|
||||||
|
-- Send message.
|
||||||
|
String'Write (Stream (Client), Message);
|
||||||
|
|
||||||
|
Build_Socket_Response_Vector :
|
||||||
|
loop
|
||||||
|
Read (Channel.all, Data, Offset);
|
||||||
|
exit when Offset = 0;
|
||||||
|
|
||||||
|
declare
|
||||||
|
Current_Line : Unbounded_String;
|
||||||
|
Current_Line_Len : Natural;
|
||||||
|
begin
|
||||||
|
for I in 1 .. Offset loop
|
||||||
|
|
||||||
|
-- Put_Line (Character'Val (Data (I))'Img);
|
||||||
|
|
||||||
|
Current_Line_Len := Length (Current_Line);
|
||||||
|
|
||||||
|
if Character'Val (Data (I)) = ASCII.CR then
|
||||||
|
Socket_Response_Vec.Append (Current_Line);
|
||||||
|
Delete (Current_Line, 1, Current_Line_Len);
|
||||||
|
elsif Character'Val (Data (I)) /= ASCII.LF then
|
||||||
|
Append (Current_Line, Character'Val (Data (I)));
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
Socket_Response_Vec.Append (Current_Line);
|
||||||
|
|
||||||
|
end;
|
||||||
|
end loop Build_Socket_Response_Vector;
|
||||||
|
|
||||||
|
Close_Socket (Socket => Client);
|
||||||
|
|
||||||
|
return Socket_Response_Vec;
|
||||||
|
|
||||||
|
exception
|
||||||
|
when Socket_Error =>
|
||||||
|
Put_Line ("Socket error");
|
||||||
|
Socket_Response_Vec.Append (To_Unbounded_String ("HTTP/1.0 500 Socket_Error"));
|
||||||
|
return Socket_Response_Vec;
|
||||||
|
|
||||||
|
end Send_To_Socket;
|
||||||
|
|
||||||
|
end Socket;
|
@ -0,0 +1,16 @@
|
|||||||
|
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||||
|
with Ada.Containers.Vectors;
|
||||||
|
|
||||||
|
package Socket is
|
||||||
|
|
||||||
|
-- Socket_Response_Vectors contains the lines of the socket response.
|
||||||
|
package Socket_Response_Vectors is new Ada.Containers.Vectors
|
||||||
|
(Index_Type => Natural, Element_Type => Unbounded_String);
|
||||||
|
|
||||||
|
use Socket_Response_Vectors;
|
||||||
|
|
||||||
|
function Send_To_Socket
|
||||||
|
(Message : in String) return Socket_Response_Vectors.Vector with
|
||||||
|
Post => not Send_To_Socket'Result.Is_Empty;
|
||||||
|
|
||||||
|
end Socket;
|
@ -0,0 +1,11 @@
|
|||||||
|
with Ada.Strings.Bounded;
|
||||||
|
|
||||||
|
package Types is
|
||||||
|
|
||||||
|
subtype MaxAllowedContainers_Type is Natural range 1 .. 20;
|
||||||
|
|
||||||
|
package Container_Name_Str is new Ada.Strings.Bounded
|
||||||
|
.Generic_Bounded_Length
|
||||||
|
(Max => 128);
|
||||||
|
|
||||||
|
end Types;
|
@ -0,0 +1,22 @@
|
|||||||
|
with Globals;
|
||||||
|
with Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
package body Utils is
|
||||||
|
|
||||||
|
function Is_Admin (User: string) return Boolean is
|
||||||
|
use Globals;
|
||||||
|
use Ada.Strings.Unbounded;
|
||||||
|
|
||||||
|
Result : Boolean := false;
|
||||||
|
begin
|
||||||
|
for e of Param_Admins loop
|
||||||
|
if user = To_String (e) then
|
||||||
|
Result := true;
|
||||||
|
return Result;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end Utils;
|
@ -0,0 +1,5 @@
|
|||||||
|
package Utils is
|
||||||
|
|
||||||
|
function Is_Admin (User: string) return Boolean;
|
||||||
|
|
||||||
|
end Utils;
|