-----------------------------------------------------------------------
--  components-util -- ASF Util Components
--  Copyright (C) 2009, 2010, 2011, 2013 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Util.Beans.Objects;
with ASF.Views;
with ASF.Views.Nodes;
package body ASF.Components.Utils is

   function Get_Line_Info (UI : in Base.UIComponent'Class) return Views.Line_Info;

   --  ------------------------------
   --  Get the line information where the component is defined.
   --  ------------------------------
   function Get_Line_Info (UI : in Base.UIComponent'Class) return Views.Line_Info is
      Tag : constant access ASF.Views.Nodes.Tag_Node'Class := UI.Get_Tag;
   begin
      if Tag /= null then
         return Tag.Get_Line_Info;
      else
         return Tag.Get_Line_Info;
      end if;
   end Get_Line_Info;
   pragma Unreferenced (Get_Line_Info);

   --  ------------------------------
   --  Get the line information where the component is defined.
   --  ------------------------------
   function Get_Line_Info (UI : in Base.UIComponent'Class) return String is
      Tag : constant access ASF.Views.Nodes.Tag_Node'Class := UI.Get_Tag;
   begin
      if Tag /= null then
         return Tag.Get_Line_Info;
      else
         return "?";
      end if;
   end Get_Line_Info;

   --  ------------------------------
   --  Get the component attribute that implements the <tt>List_Bean</tt> interface.
   --  Returns null if the attribute is not found or does not implement the interface.
   --  ------------------------------
   function Get_List_Bean (UI      : in Base.UIComponent'Class;
                           Name    : in String;
                           Context : in ASF.Contexts.Faces.Faces_Context'Class)
                           return Util.Beans.Basic.List_Bean_Access is
      use type Util.Beans.Objects.Data_Type;

      Value : constant Util.Beans.Objects.Object := UI.Get_Attribute (Context, Name);
      Kind  : constant Util.Beans.Objects.Data_Type := Util.Beans.Objects.Get_Type (Value);
      Bean  : access Util.Beans.Basic.Readonly_Bean'Class;
      List  : Util.Beans.Basic.List_Bean_Access;
   begin
      --  Check that we have a List_Bean but do not complain if we have a null value.
      if Kind /= Util.Beans.Objects.TYPE_BEAN then
         if Kind /= Util.Beans.Objects.TYPE_NULL then
            ASF.Components.Base.Log_Error (UI, "Invalid list bean (found a {0})",
                                           Util.Beans.Objects.Get_Type_Name (Value));
         end if;
         return null;
      end if;

      Bean := Util.Beans.Objects.To_Bean (Value);
      if Bean = null or else not (Bean.all in Util.Beans.Basic.List_Bean'Class) then
         ASF.Components.Base.Log_Error (UI, "Invalid list bean: it does not implement"
                                        &" 'List_Bean' interface");
         return null;
      end if;
      List := Util.Beans.Basic.List_Bean'Class (Bean.all)'Unchecked_Access;
      return List;
   end Get_List_Bean;

end ASF.Components.Utils;

-----------------------------------------------------------------------
--  components-util -- ASF Util Components
--  Copyright (C) 2009, 2010, 2011, 2013, 2015 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Util.Beans.Objects;
with ASF.Views;
with ASF.Views.Nodes;
package body ASF.Components.Utils is

   function Get_Line_Info (UI : in Base.UIComponent'Class) return Views.Line_Info;

   --  ------------------------------
   --  Get the line information where the component is defined.
   --  ------------------------------
   function Get_Line_Info (UI : in Base.UIComponent'Class) return Views.Line_Info is
      Tag : constant access ASF.Views.Nodes.Tag_Node'Class := UI.Get_Tag;
   begin
      if Tag /= null then
         return Tag.Get_Line_Info;
      else
         return Tag.Get_Line_Info;
      end if;
   end Get_Line_Info;
   pragma Unreferenced (Get_Line_Info);

   --  ------------------------------
   --  Get the line information where the component is defined.
   --  ------------------------------
   function Get_Line_Info (UI : in Base.UIComponent'Class) return String is
      Tag : constant access ASF.Views.Nodes.Tag_Node'Class := UI.Get_Tag;
   begin
      if Tag /= null then
         return Tag.Get_Line_Info;
      else
         return "?";
      end if;
   end Get_Line_Info;

   --  ------------------------------
   --  Get the component attribute that implements the <tt>List_Bean</tt> interface.
   --  Returns null if the attribute is not found or does not implement the interface.
   --  ------------------------------
   function Get_List_Bean (UI      : in Base.UIComponent'Class;
                           Name    : in String;
                           Context : in ASF.Contexts.Faces.Faces_Context'Class)
                           return Util.Beans.Basic.List_Bean_Access is
      use type Util.Beans.Objects.Data_Type;

      Value : constant Util.Beans.Objects.Object := UI.Get_Attribute (Context, Name);
      Kind  : constant Util.Beans.Objects.Data_Type := Util.Beans.Objects.Get_Type (Value);
      Bean  : access Util.Beans.Basic.Readonly_Bean'Class;
      List  : Util.Beans.Basic.List_Bean_Access;
   begin
      --  Check that we have a List_Bean but do not complain if we have a null value.
      if Kind /= Util.Beans.Objects.TYPE_BEAN then
         if Kind /= Util.Beans.Objects.TYPE_NULL then
            ASF.Components.Base.Log_Error (UI, "Invalid list bean (found a {0})",
                                           Util.Beans.Objects.Get_Type_Name (Value));
         end if;
         return null;
      end if;

      Bean := Util.Beans.Objects.To_Bean (Value);
      if Bean = null or else not (Bean.all in Util.Beans.Basic.List_Bean'Class) then
         ASF.Components.Base.Log_Error (UI, "Invalid list bean: it does not implement"
                                        & " 'List_Bean' interface");
         return null;
      end if;
      List := Util.Beans.Basic.List_Bean'Class (Bean.all)'Unchecked_Access;
      return List;
   end Get_List_Bean;

end ASF.Components.Utils;

Fix style compilation warning

Fix style compilation warning


-----------------------------------------------------------------------
--  gen-artifacts-docs-markdown -- Artifact for GitHub Markdown documentation format
--  Copyright (C) 2015, 2017, 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Strings.Fixed;
with Ada.Strings.Maps;
with Util.Strings;
with Util.Log.Loggers;
package body Gen.Artifacts.Docs.Markdown is

   use type Ada.Strings.Maps.Character_Set;

   function Has_Scheme (Link : in String) return Boolean;
   function Is_Image (Link : in String) return Boolean;

   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("Gen.Artifacts.Docs.Mark");

   Marker : constant Ada.Strings.Maps.Character_Set
     := Ada.Strings.Maps.To_Set (" .,;:!?")
     or Ada.Strings.Maps.To_Set (ASCII.HT)
     or Ada.Strings.Maps.To_Set (ASCII.VT)
     or Ada.Strings.Maps.To_Set (ASCII.CR)
     or Ada.Strings.Maps.To_Set (ASCII.LF);

   --  ------------------------------
   --  Get the document name from the file document (ex: <name>.wiki or <name>.md).
   --  ------------------------------
   overriding
   function Get_Document_Name (Formatter : in Document_Formatter;
                               Document  : in File_Document) return String is
      pragma Unreferenced (Formatter);
   begin
      return Ada.Strings.Unbounded.To_String (Document.Name) & ".md";
   end Get_Document_Name;

   --  ------------------------------
   --  Start a new document.
   --  ------------------------------
   overriding
   procedure Start_Document (Formatter : in out Document_Formatter;
                             Document  : in File_Document;
                             File      : in Ada.Text_IO.File_Type) is
      pragma Unreferenced (Formatter);
   begin
      if Document.Print_Footer then
         Ada.Text_IO.Put_Line (File, "# " & Ada.Strings.Unbounded.To_String (Document.Title));
         Ada.Text_IO.New_Line (File);
      end if;
   end Start_Document;

   --  ------------------------------
   --  Return True if the link has either a http:// or a https:// scheme.
   --  ------------------------------
   function Has_Scheme (Link : in String) return Boolean is
   begin
      if Link'Length < 8 then
         return False;
      elsif Link (Link'First .. Link'First + 6) = "http://" then
         return True;
      elsif Link (Link'First .. Link'First + 7) = "https://" then
         return True;
      else
         return False;
      end if;
   end Has_Scheme;

   function Is_Image (Link : in String) return Boolean is
   begin
      if Link'Length < 4 then
         return False;
      elsif Link (Link'Last - 3 .. Link'Last) = ".png" then
         return True;
      elsif Link (Link'Last - 3 .. Link'Last) = ".jpg" then
         return True;
      elsif Link (Link'Last - 3 .. Link'Last) = ".gif" then
         return True;
      else
         Log.Info ("Link {0} not an image", Link);
         return False;
      end if;
   end Is_Image;

   procedure Write_Text_Auto_Links (Formatter : in out Document_Formatter;
                                    File      : in Ada.Text_IO.File_Type;
                                    Text      : in String) is
      Start : Natural := Text'First;
      Last  : Natural := Text'Last;
      Link  : Util.Strings.Maps.Cursor;
      Pos   : Natural;
   begin
      Log.Debug ("Auto link |{0}|", Text);
      loop
         --  Emit spaces at beginning of line or words.
         while Start <= Text'Last and then Ada.Strings.Maps.Is_In (Text (Start), Marker) loop
            Ada.Text_IO.Put (File, Text (Start));
            Start := Start + 1;
         end loop;
         exit when Start > Text'Last;

         --  Find a possible link.
         Link := Formatter.Links.Find (Text (Start .. Last));
         if Util.Strings.Maps.Has_Element (Link) then
            Ada.Text_IO.Put (File, "[");
            Ada.Text_IO.Put (File, Text (Start .. Last));
            Ada.Text_IO.Put (File, "](");
            Ada.Text_IO.Put (File, Util.Strings.Maps.Element (Link));
            Ada.Text_IO.Put (File, ")");
            Start := Last + 1;
            Last := Text'Last;
         else
            Pos := Ada.Strings.Fixed.Index (Text (Start .. Last), Marker,
                                            Going => Ada.Strings.Backward);
            if Pos = 0 then
               Ada.Text_IO.Put (File, Text (Start .. Last));
               Start := Last + 1;
               Last := Text'Last;
            else
               Last := Pos - 1;

               --  Skip spaces at end of words for the search.
               while Last > Start and then Ada.Strings.Maps.Is_In (Text (Last), Marker) loop
                  Last := Last - 1;
               end loop;
            end if;
         end if;
      end loop;
   end Write_Text_Auto_Links;

   --  ------------------------------
   --  Write a line doing some link transformation for Markdown.
   --  ------------------------------
   procedure Write_Text (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Text      : in String) is
      Pos      : Natural;
      Start    : Natural := Text'First;
      End_Pos  : Natural;
      Last_Pos : Natural;
   begin
      --  Transform links
      --  [Link]   -> [[Link]]
      --  [Link Title] -> [[Title|Link]]
      --
      --  Do not change the following links:
      --  [[Link|Title]]
      loop
         Pos := Util.Strings.Index (Text, '[', Start);
         if Pos = 0 or else Pos = Text'Last then
            Formatter.Write_Text_Auto_Links (File, Text (Start .. Text'Last));
            return;
         end if;
         Formatter.Write_Text_Auto_Links (File, Text (Start .. Pos - 1));

         if Pos - 1 >= Text'First and then (Text (Pos - 1) = '\' or Text (Pos - 1) = '`') then
            Ada.Text_IO.Put (File, "[");
            Start := Pos + 1;

         --  Parse a markdown link format.
         elsif Text (Pos + 1) = '[' then
            Start := Pos + 2;
            Pos := Util.Strings.Index (Text, ']', Pos + 2);
            if Pos = 0 then
               if Is_Image (Text (Start .. Text'Last)) then
                  Ada.Text_IO.Put (File, Text (Start - 2 .. Text'Last));
               else
                  Ada.Text_IO.Put (File, Text (Start - 2 .. Text'Last));
               end if;
               return;
            end if;
            if Is_Image (Text (Start .. Pos - 1)) then
               Ada.Text_IO.Put (File, "![](");
               Ada.Text_IO.Put (File, Text (Start .. Pos - 1));
               Ada.Text_IO.Put (File, ")");
               Start := Pos + 2;
            else
               Ada.Text_IO.Put (File, Text (Start .. Pos));
               Start := Pos + 1;
            end if;
         else
            Pos := Pos + 1;
            End_Pos := Pos;
            while End_Pos < Text'Last and Text (End_Pos) /= ' ' and Text (End_Pos) /= ']' loop
               End_Pos := End_Pos + 1;
            end loop;
            Last_Pos := End_Pos;
            while Last_Pos < Text'Last and Text (Last_Pos) /= ']' loop
               Last_Pos := Last_Pos + 1;
            end loop;
            if Is_Image (Text (Pos .. Last_Pos - 1)) then
               Ada.Text_IO.Put (File, "![");
               --  Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "](");
               Ada.Text_IO.Put (File, Text (Pos .. Last_Pos - 1));
               Ada.Text_IO.Put (File, ")");
            elsif Is_Image (Text (Pos .. End_Pos)) then
               Last_Pos := Last_Pos - 1;
               Ada.Text_IO.Put (File, "![");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "](");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, ")");
            elsif Has_Scheme (Text (Pos .. End_Pos)) then
               Ada.Text_IO.Put (File, "[");
               Ada.Text_IO.Put (File, Text (End_Pos + 1 .. Last_Pos));
               Ada.Text_IO.Put (File, "(");
               Ada.Text_IO.Put (File,
                                Ada.Strings.Fixed.Trim (Text (Pos .. End_Pos), Ada.Strings.Both));
               Ada.Text_IO.Put (File, ")");
            else
               Last_Pos := Last_Pos - 1;
               Ada.Text_IO.Put (File, "[[");
               Ada.Text_IO.Put (File, Text (End_Pos + 1 .. Last_Pos));
               Ada.Text_IO.Put (File, "|");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "]");
            end if;
            Start := Last_Pos + 1;
         end if;
      end loop;
   end Write_Text;

   --  ------------------------------
   --  Write a line in the document.
   --  ------------------------------
   procedure Write_Line (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Line      : in String) is
   begin
      if Formatter.Need_Newline then
         Ada.Text_IO.New_Line (File);
         Formatter.Need_Newline := False;
      end if;
      if Formatter.Mode = L_START_CODE and then Line'Length > 2
        and then Line (Line'First .. Line'First + 1) = "  "
      then
         Ada.Text_IO.Put_Line (File, Line (Line'First + 2 .. Line'Last));
      elsif Formatter.Mode = L_TEXT then
         Formatter.Write_Text (File, Line);
         Ada.Text_IO.New_Line (File);
      else
         Ada.Text_IO.Put_Line (File, Line);
      end if;
   end Write_Line;

   --  ------------------------------
   --  Write a line in the target document formatting the line if necessary.
   --  ------------------------------
   overriding
   procedure Write_Line (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Line      : in Line_Type) is
   begin
      case Line.Kind is
         when L_LIST =>
            Ada.Text_IO.New_Line (File);
            Ada.Text_IO.Put (File, Line.Content);
            Formatter.Need_Newline := True;
            Formatter.Mode := Line.Kind;

         when L_LIST_ITEM =>
            Ada.Text_IO.Put (File, Line.Content);
            Formatter.Need_Newline := True;

         when L_START_CODE =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "```Ada");

         when L_END_CODE =>
            Formatter.Mode := L_TEXT;
            Formatter.Write_Line (File, "```");

         when L_TEXT =>
            Formatter.Mode := L_TEXT;
            Formatter.Write_Line (File, Line.Content);

         when L_HEADER_1 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "# " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_2 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "## " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_3 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "### " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_4 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "#### " & Line.Content);
            Formatter.Mode := L_TEXT;

         when others =>
            null;

      end case;
   end Write_Line;

   --  ------------------------------
   --  Finish the document.
   --  ------------------------------
   overriding
   procedure Finish_Document (Formatter : in out Document_Formatter;
                              Document  : in File_Document;
                              File      : in Ada.Text_IO.File_Type;
                              Source    : in String) is
      pragma Unreferenced (Formatter);
   begin
      Ada.Text_IO.New_Line (File);
      if Document.Print_Footer then
         Ada.Text_IO.Put_Line (File, "----");
         Ada.Text_IO.Put_Line (File,
                               "[Generated by Dynamo](https://github.com/stcarrez/dynamo) from *"
                               & Source & "*");
      end if;
   end Finish_Document;

end Gen.Artifacts.Docs.Markdown;

-----------------------------------------------------------------------
--  gen-artifacts-docs-markdown -- Artifact for GitHub Markdown documentation format
--  Copyright (C) 2015, 2017, 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Strings.Fixed;
with Ada.Strings.Maps;
with Util.Strings;
with Util.Log.Loggers;
package body Gen.Artifacts.Docs.Markdown is

   use type Ada.Strings.Maps.Character_Set;

   function Has_Scheme (Link : in String) return Boolean;
   function Is_Image (Link : in String) return Boolean;

   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("Gen.Artifacts.Docs.Mark");

   Marker : constant Ada.Strings.Maps.Character_Set
     := Ada.Strings.Maps.To_Set (" .,;:!?")
     or Ada.Strings.Maps.To_Set (ASCII.HT)
     or Ada.Strings.Maps.To_Set (ASCII.VT)
     or Ada.Strings.Maps.To_Set (ASCII.CR)
     or Ada.Strings.Maps.To_Set (ASCII.LF);

   --  ------------------------------
   --  Get the document name from the file document (ex: <name>.wiki or <name>.md).
   --  ------------------------------
   overriding
   function Get_Document_Name (Formatter : in Document_Formatter;
                               Document  : in File_Document) return String is
      pragma Unreferenced (Formatter);
   begin
      return Ada.Strings.Unbounded.To_String (Document.Name) & ".md";
   end Get_Document_Name;

   --  ------------------------------
   --  Start a new document.
   --  ------------------------------
   overriding
   procedure Start_Document (Formatter : in out Document_Formatter;
                             Document  : in File_Document;
                             File      : in Ada.Text_IO.File_Type) is
      pragma Unreferenced (Formatter);
   begin
      if Document.Print_Footer then
         Ada.Text_IO.Put_Line (File, "# " & Ada.Strings.Unbounded.To_String (Document.Title));
         Ada.Text_IO.New_Line (File);
      end if;
   end Start_Document;

   --  ------------------------------
   --  Return True if the link has either a http:// or a https:// scheme.
   --  ------------------------------
   function Has_Scheme (Link : in String) return Boolean is
   begin
      if Link'Length < 8 then
         return False;
      elsif Link (Link'First .. Link'First + 6) = "http://" then
         return True;
      elsif Link (Link'First .. Link'First + 7) = "https://" then
         return True;
      else
         return False;
      end if;
   end Has_Scheme;

   function Is_Image (Link : in String) return Boolean is
   begin
      if Link'Length < 4 then
         return False;
      elsif Link (Link'Last - 3 .. Link'Last) = ".png" then
         return True;
      elsif Link (Link'Last - 3 .. Link'Last) = ".jpg" then
         return True;
      elsif Link (Link'Last - 3 .. Link'Last) = ".gif" then
         return True;
      else
         Log.Info ("Link {0} not an image", Link);
         return False;
      end if;
   end Is_Image;

   procedure Write_Text_Auto_Links (Formatter : in out Document_Formatter;
                                    File      : in Ada.Text_IO.File_Type;
                                    Text      : in String) is
      Start : Natural := Text'First;
      Last  : Natural := Text'Last;
      Link  : Util.Strings.Maps.Cursor;
      Pos   : Natural;
   begin
      Log.Debug ("Auto link |{0}|", Text);
      loop
         --  Emit spaces at beginning of line or words.
         while Start <= Text'Last and then Ada.Strings.Maps.Is_In (Text (Start), Marker) loop
            Ada.Text_IO.Put (File, Text (Start));
            Start := Start + 1;
         end loop;
         exit when Start > Text'Last;

         --  Find a possible link.
         Link := Formatter.Links.Find (Text (Start .. Last));
         if Util.Strings.Maps.Has_Element (Link) then
            Ada.Text_IO.Put (File, "[");
            Ada.Text_IO.Put (File, Text (Start .. Last));
            Ada.Text_IO.Put (File, "](");
            Ada.Text_IO.Put (File, Util.Strings.Maps.Element (Link));
            Ada.Text_IO.Put (File, ")");
            Start := Last + 1;
            Last := Text'Last;
         else
            Pos := Ada.Strings.Fixed.Index (Text (Start .. Last), Marker,
                                            Going => Ada.Strings.Backward);
            if Pos = 0 then
               Ada.Text_IO.Put (File, Text (Start .. Last));
               Start := Last + 1;
               Last := Text'Last;
            else
               Last := Pos - 1;

               --  Skip spaces at end of words for the search.
               while Last > Start and then Ada.Strings.Maps.Is_In (Text (Last), Marker) loop
                  Last := Last - 1;
               end loop;
            end if;
         end if;
      end loop;
   end Write_Text_Auto_Links;

   --  ------------------------------
   --  Write a line doing some link transformation for Markdown.
   --  ------------------------------
   procedure Write_Text (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Text      : in String) is
      Pos      : Natural;
      Start    : Natural := Text'First;
      End_Pos  : Natural;
      Last_Pos : Natural;
   begin
      --  Transform links
      --  [Link]   -> [[Link]]
      --  [Link Title] -> [[Title|Link]]
      --
      --  Do not change the following links:
      --  [[Link|Title]]
      loop
         Pos := Util.Strings.Index (Text, '[', Start);
         if Pos = 0 or else Pos = Text'Last then
            Formatter.Write_Text_Auto_Links (File, Text (Start .. Text'Last));
            return;
         end if;
         Formatter.Write_Text_Auto_Links (File, Text (Start .. Pos - 1));

         if Pos - 1 >= Text'First and then (Text (Pos - 1) = '\' or Text (Pos - 1) = '`') then
            Ada.Text_IO.Put (File, "[");
            Start := Pos + 1;

         --  Parse a markdown link format.
         elsif Text (Pos + 1) = '[' then
            Start := Pos + 2;
            Pos := Util.Strings.Index (Text, ']', Pos + 2);
            if Pos = 0 then
               if Is_Image (Text (Start .. Text'Last)) then
                  Ada.Text_IO.Put (File, Text (Start - 2 .. Text'Last));
               else
                  Ada.Text_IO.Put (File, Text (Start - 2 .. Text'Last));
               end if;
               return;
            end if;
            if Is_Image (Text (Start .. Pos - 1)) then
               Ada.Text_IO.Put (File, "![](");
               Ada.Text_IO.Put (File, Text (Start .. Pos - 1));
               Ada.Text_IO.Put (File, ")");
               Start := Pos + 2;
            else
               Ada.Text_IO.Put (File, Text (Start .. Pos));
               Start := Pos + 1;
            end if;
         else
            Pos := Pos + 1;
            End_Pos := Pos;
            while End_Pos < Text'Last and Text (End_Pos) /= ' ' and Text (End_Pos) /= ']' loop
               End_Pos := End_Pos + 1;
            end loop;
            Last_Pos := End_Pos;
            while Last_Pos < Text'Last and Text (Last_Pos) /= ']' loop
               Last_Pos := Last_Pos + 1;
            end loop;
            if Is_Image (Text (Pos .. Last_Pos - 1)) then
               Ada.Text_IO.Put (File, "![");
               --  Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "](");
               Ada.Text_IO.Put (File, Text (Pos .. Last_Pos - 1));
               Ada.Text_IO.Put (File, ")");
            elsif Is_Image (Text (Pos .. End_Pos)) then
               Last_Pos := Last_Pos - 1;
               Ada.Text_IO.Put (File, "![");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "](");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, ")");
            elsif Has_Scheme (Text (Pos .. End_Pos)) then
               Ada.Text_IO.Put (File, "[");
               Ada.Text_IO.Put (File, Text (End_Pos + 1 .. Last_Pos));
               Ada.Text_IO.Put (File, "(");
               Ada.Text_IO.Put (File,
                                Ada.Strings.Fixed.Trim (Text (Pos .. End_Pos), Ada.Strings.Both));
               Ada.Text_IO.Put (File, ")");
            else
               Last_Pos := Last_Pos - 1;
               Ada.Text_IO.Put (File, "[[");
               Ada.Text_IO.Put (File, Text (End_Pos + 1 .. Last_Pos));
               Ada.Text_IO.Put (File, "|");
               Ada.Text_IO.Put (File, Text (Pos .. End_Pos));
               Ada.Text_IO.Put (File, "]");
            end if;
            Start := Last_Pos + 1;
         end if;
      end loop;
   end Write_Text;

   --  ------------------------------
   --  Write a line in the document.
   --  ------------------------------
   procedure Write_Line (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Line      : in String) is
   begin
      if Formatter.Need_Newline then
         Ada.Text_IO.New_Line (File);
         Formatter.Need_Newline := False;
      end if;
      if Formatter.Mode = L_START_CODE and then Line'Length > 2
        and then Line (Line'First .. Line'First + 1) = "  "
      then
         Ada.Text_IO.Put_Line (File, Line (Line'First + 2 .. Line'Last));
      elsif Formatter.Mode = L_TEXT then
         Formatter.Write_Text (File, Line);
         Ada.Text_IO.New_Line (File);
      else
         Ada.Text_IO.Put_Line (File, Line);
      end if;
   end Write_Line;

   --  ------------------------------
   --  Write a line in the target document formatting the line if necessary.
   --  ------------------------------
   overriding
   procedure Write_Line (Formatter : in out Document_Formatter;
                         File      : in Ada.Text_IO.File_Type;
                         Line      : in Line_Type) is
   begin
      case Line.Kind is
         when L_LIST =>
            Ada.Text_IO.New_Line (File);
            Ada.Text_IO.Put (File, Line.Content);
            Formatter.Need_Newline := True;
            Formatter.Mode := Line.Kind;

         when L_LIST_ITEM =>
            Ada.Text_IO.Put (File, Line.Content);
            Formatter.Need_Newline := True;

         when L_START_CODE =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "```Ada");

         when L_END_CODE =>
            Formatter.Mode := L_TEXT;
            Formatter.Write_Line (File, "```");

         when L_TEXT =>
            if Formatter.Mode /= L_START_CODE then
               Formatter.Mode := L_TEXT;
            end if;
            Formatter.Write_Line (File, Line.Content);

         when L_HEADER_1 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "# " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_2 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "## " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_3 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "### " & Line.Content);
            Formatter.Mode := L_TEXT;

         when L_HEADER_4 =>
            Formatter.Mode := Line.Kind;
            Formatter.Write_Line (File, "#### " & Line.Content);
            Formatter.Mode := L_TEXT;

         when others =>
            null;

      end case;
   end Write_Line;

   --  ------------------------------
   --  Finish the document.
   --  ------------------------------
   overriding
   procedure Finish_Document (Formatter : in out Document_Formatter;
                              Document  : in File_Document;
                              File      : in Ada.Text_IO.File_Type;
                              Source    : in String) is
      pragma Unreferenced (Formatter);
   begin
      Ada.Text_IO.New_Line (File);
      if Document.Print_Footer then
         Ada.Text_IO.Put_Line (File, "----");
         Ada.Text_IO.Put_Line (File,
                               "[Generated by Dynamo](https://github.com/stcarrez/dynamo) from *"
                               & Source & "*");
      end if;
   end Finish_Document;

end Gen.Artifacts.Docs.Markdown;

Fix formatting of code blocks

Fix formatting of code blocks


--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2012 Felix Krause <contact@flyx.org>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

private with GL.Low_Level;
with GL.Types;

package GL.Toggles is
   pragma Preelaborate;

   type Toggle_State is (Disabled, Enabled);

   type Toggle is (Line_Smooth, Polygon_Smooth, Cull_Face, Depth_Test,
                   Stencil_Test, Dither, Blend, Color_Logic_Op, Scissor_Test,
                   Polygon_Offset_Point, Polygon_Offset_Line,
                   Clip_Distance_0, Clip_Distance_1, Clip_Distance_2, Clip_Distance_3,
                   Clip_Distance_4, Clip_Distance_5, Clip_Distance_6, Clip_Distance_7,
                   Polygon_Offset_Fill, Multisample,
                   Sample_Alpha_To_Coverage, Sample_Alpha_To_One, Sample_Coverage,
                   Debug_Output_Synchronous,
                   Program_Point_Size, Depth_Clamp,
                   Texture_Cube_Map_Seamless, Sample_Shading,
                   Rasterizer_Discard, Primitive_Restart_Fixed_Index,
                   Framebuffer_SRGB, Sample_Mask, Primitive_Restart,
                   Debug_Output);

   procedure Enable  (Subject : Toggle);
   procedure Disable (Subject : Toggle);

   procedure Set (Subject : Toggle; Value : Toggle_State);
   function State (Subject : Toggle) return Toggle_State;

   type Toggle_Indexed is (Blend, Scissor_Test);

   procedure Enable  (Subject : Toggle_Indexed; Index : Types.UInt);
   procedure Disable (Subject : Toggle_Indexed; Index : Types.UInt);

   procedure Set (Subject : Toggle_Indexed; Index : Types.UInt; Value : Toggle_State);
   function State (Subject : Toggle_Indexed; Index : Types.UInt) return Toggle_State;

private

   for Toggle use (Line_Smooth               => 16#0B20#,
                   Polygon_Smooth            => 16#0B41#,
                   Cull_Face                 => 16#0B44#,
                   Depth_Test                => 16#0B71#,
                   Stencil_Test              => 16#0B90#,
                   Dither                    => 16#0BD0#,
                   Blend                     => 16#0BE2#,
                   Color_Logic_Op            => 16#0BF2#,
                   Scissor_Test              => 16#0C11#,
                   Polygon_Offset_Point      => 16#2A01#,
                   Polygon_Offset_Line       => 16#2A02#,
                   Clip_Distance_0           => 16#3000#,
                   Clip_Distance_1           => 16#3001#,
                   Clip_Distance_2           => 16#3002#,
                   Clip_Distance_3           => 16#3003#,
                   Clip_Distance_4           => 16#3004#,
                   Clip_Distance_5           => 16#3005#,
                   Clip_Distance_6           => 16#3006#,
                   Clip_Distance_7           => 16#3007#,
                   Polygon_Offset_Fill       => 16#8037#,
                   Multisample               => 16#809D#,
                   Sample_Alpha_To_Coverage  => 16#809E#,
                   Sample_Alpha_To_One       => 16#809F#,
                   Sample_Coverage           => 16#80A0#,
                   Debug_Output_Synchronous  => 16#8242#,
                   Program_Point_Size        => 16#8642#,
                   Depth_Clamp               => 16#864F#,
                   Texture_Cube_Map_Seamless => 16#884F#,
                   Sample_Shading            => 16#8C36#,
                   Rasterizer_Discard        => 16#8C89#,
                   Primitive_Restart_Fixed_Index => 16#8D69#,
                   Framebuffer_SRGB          => 16#8DB9#,
                   Sample_Mask               => 16#8E51#,
                   Primitive_Restart         => 16#8F9D#,
                   Debug_Output              => 16#92E0#);
   for Toggle'Size use Low_Level.Enum'Size;

   for Toggle_Indexed use
     (Blend        => 16#0BE2#,
      Scissor_Test => 16#0C11#);
   for Toggle_Indexed'Size use Low_Level.Enum'Size;

end GL.Toggles;

--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2012 Felix Krause <contact@flyx.org>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

private with GL.Low_Level;
with GL.Types;

package GL.Toggles is
   pragma Preelaborate;

   type Toggle_State is (Disabled, Enabled);

   type Toggle is (Cull_Face, Depth_Test,
                   Stencil_Test, Dither, Blend, Color_Logic_Op, Scissor_Test,
                   Polygon_Offset_Point, Polygon_Offset_Line,
                   Clip_Distance_0, Clip_Distance_1, Clip_Distance_2, Clip_Distance_3,
                   Clip_Distance_4, Clip_Distance_5, Clip_Distance_6, Clip_Distance_7,
                   Polygon_Offset_Fill, Multisample,
                   Sample_Alpha_To_Coverage, Sample_Alpha_To_One, Sample_Coverage,
                   Debug_Output_Synchronous,
                   Program_Point_Size, Depth_Clamp,
                   Texture_Cube_Map_Seamless, Sample_Shading,
                   Rasterizer_Discard, Primitive_Restart_Fixed_Index,
                   Framebuffer_SRGB, Sample_Mask, Primitive_Restart,
                   Debug_Output);

   procedure Enable  (Subject : Toggle);
   procedure Disable (Subject : Toggle);

   procedure Set (Subject : Toggle; Value : Toggle_State);
   function State (Subject : Toggle) return Toggle_State;

   type Toggle_Indexed is (Blend, Scissor_Test);

   procedure Enable  (Subject : Toggle_Indexed; Index : Types.UInt);
   procedure Disable (Subject : Toggle_Indexed; Index : Types.UInt);

   procedure Set (Subject : Toggle_Indexed; Index : Types.UInt; Value : Toggle_State);
   function State (Subject : Toggle_Indexed; Index : Types.UInt) return Toggle_State;

private

   for Toggle use (Cull_Face                 => 16#0B44#,
                   Depth_Test                => 16#0B71#,
                   Stencil_Test              => 16#0B90#,
                   Dither                    => 16#0BD0#,
                   Blend                     => 16#0BE2#,
                   Color_Logic_Op            => 16#0BF2#,
                   Scissor_Test              => 16#0C11#,
                   Polygon_Offset_Point      => 16#2A01#,
                   Polygon_Offset_Line       => 16#2A02#,
                   Clip_Distance_0           => 16#3000#,
                   Clip_Distance_1           => 16#3001#,
                   Clip_Distance_2           => 16#3002#,
                   Clip_Distance_3           => 16#3003#,
                   Clip_Distance_4           => 16#3004#,
                   Clip_Distance_5           => 16#3005#,
                   Clip_Distance_6           => 16#3006#,
                   Clip_Distance_7           => 16#3007#,
                   Polygon_Offset_Fill       => 16#8037#,
                   Multisample               => 16#809D#,
                   Sample_Alpha_To_Coverage  => 16#809E#,
                   Sample_Alpha_To_One       => 16#809F#,
                   Sample_Coverage           => 16#80A0#,
                   Debug_Output_Synchronous  => 16#8242#,
                   Program_Point_Size        => 16#8642#,
                   Depth_Clamp               => 16#864F#,
                   Texture_Cube_Map_Seamless => 16#884F#,
                   Sample_Shading            => 16#8C36#,
                   Rasterizer_Discard        => 16#8C89#,
                   Primitive_Restart_Fixed_Index => 16#8D69#,
                   Framebuffer_SRGB          => 16#8DB9#,
                   Sample_Mask               => 16#8E51#,
                   Primitive_Restart         => 16#8F9D#,
                   Debug_Output              => 16#92E0#);
   for Toggle'Size use Low_Level.Enum'Size;

   for Toggle_Indexed use
     (Blend        => 16#0BE2#,
      Scissor_Test => 16#0C11#);
   for Toggle_Indexed'Size use Low_Level.Enum'Size;

end GL.Toggles;

gl: Remove old toggles to do line/polygon smoothing

Use MSAA and/or post-processing algorithms like FXAA, SMAA, or CMAA.

Signed-off-by: onox <34c1d3d2d1347bea60a26f46574de21a7a79b6d5@gmail.com>


-----------------------------------------------------------------------
--  atlas-microblog-beans -- Beans for module microblog
--  Copyright (C) 2012 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Strings.Unbounded;

with Util.Beans.Basic;
with Util.Beans.Objects;
with Util.Beans.Methods;
with Atlas.Microblog.Modules;
with Atlas.Microblog.Models;
package Atlas.Microblog.Beans is

   type Microblog_Bean is new Util.Beans.Basic.Bean
     and Util.Beans.Methods.Method_Bean with record
      Module : Atlas.Microblog.Modules.Microblog_Module_Access := null;
      Post   : Atlas.Microblog.Models.Mblog_Ref;
   end record;
   type Microblog_Bean_Access is access all Microblog_Bean'Class;

   --  Get the value identified by the name.
   overriding
   function Get_Value (From : in Microblog_Bean;
                       Name : in String) return Util.Beans.Objects.Object;

   --  Set the value identified by the name.
   overriding
   procedure Set_Value (From  : in out Microblog_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object);

   --  This bean provides some methods that can be used in a Method_Expression
   overriding
   function Get_Method_Bindings (From : in Microblog_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access;

   --  Post the microblog
   procedure Post (Bean    : in out Microblog_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String);

   --  Create the Microblog_Bean bean instance.
   function Create_Microblog_Bean (Module : in Atlas.Microblog.Modules.Microblog_Module_Access)
      return Util.Beans.Basic.Readonly_Bean_Access;

   --  Create the a bean to display the list of microblog posts.
   function Create_List_Bean (Module : in Atlas.Microblog.Modules.Microblog_Module_Access)
                                   return Util.Beans.Basic.Readonly_Bean_Access;

end Atlas.Microblog.Beans;

-----------------------------------------------------------------------
--  atlas-microblog-beans -- Beans for module microblog
--  Copyright (C) 2012, 2017 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Strings.Unbounded;

with Util.Beans.Basic;
with Util.Beans.Objects;
with Util.Beans.Methods;
with AWA.Events;
with Atlas.Microblog.Modules;
with Atlas.Microblog.Models;
package Atlas.Microblog.Beans is

   type Microblog_Bean is new Util.Beans.Basic.Bean
     and Util.Beans.Methods.Method_Bean with record
      Module : Atlas.Microblog.Modules.Microblog_Module_Access := null;
      Post   : Atlas.Microblog.Models.Mblog_Ref;
   end record;
   type Microblog_Bean_Access is access all Microblog_Bean'Class;

   --  Get the value identified by the name.
   overriding
   function Get_Value (From : in Microblog_Bean;
                       Name : in String) return Util.Beans.Objects.Object;

   --  Set the value identified by the name.
   overriding
   procedure Set_Value (From  : in out Microblog_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object);

   --  This bean provides some methods that can be used in a Method_Expression
   overriding
   function Get_Method_Bindings (From : in Microblog_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access;

   --  Post the microblog
   procedure Post (Bean    : in out Microblog_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String);

   --  Post a message when some event is received.
   procedure Post (Bean    : in out Microblog_Bean;
                   Event   : in AWA.Events.Module_Event'Class);

   --  Create the Microblog_Bean bean instance.
   function Create_Microblog_Bean (Module : in Atlas.Microblog.Modules.Microblog_Module_Access)
      return Util.Beans.Basic.Readonly_Bean_Access;

   --  Create the a bean to display the list of microblog posts.
   function Create_List_Bean (Module : in Atlas.Microblog.Modules.Microblog_Module_Access)
                                   return Util.Beans.Basic.Readonly_Bean_Access;

end Atlas.Microblog.Beans;

Declare Post procedure with an event as parameter


-----------------------------------------------------------------------
--  Util.Beans.Objects.Maps -- Object maps
--  Copyright (C) 2010, 2011, 2012, 2017 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings.Hash;
with Util.Beans.Basic;
package Util.Beans.Objects.Maps is

   package Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type        => String,
                                                Element_Type    => Object,
                                                Hash            => Ada.Strings.Hash,
                                                Equivalent_Keys => "=");

   subtype Cursor is Maps.Cursor;
   subtype Map is Maps.Map;

   --  Make all the Maps operations available (a kind of 'use Maps' for anybody).
   function Length (Container : in Map) return Ada.Containers.Count_Type renames Maps.Length;
   function Is_Empty (Container : in Map) return Boolean renames Maps.Is_Empty;
   procedure Clear (Container : in out Map) renames Maps.Clear;
   function Key (Position : Cursor) return String renames Maps.Key;

   procedure Include (Container : in out Map;
                      Key : in String;
                      New_Item : in Object) renames Maps.Include;
   procedure Query_Element (Position : in Cursor;
                            Process  : not null access procedure (Key     : String;
                                                                  Element : Object))
                            renames Maps.Query_Element;

   function Has_Element (Position : Cursor) return Boolean renames Maps.Has_Element;
   function Element (Position : Cursor) return Object renames Maps.Element;
   procedure Next (Position : in out Cursor) renames Maps.Next;
   function Next (Position : Cursor) return Cursor renames Maps.Next;
   function Equivalent_Keys (Left, Right : Cursor) return Boolean renames Maps.Equivalent_Keys;
   function Equivalent_Keys (Left : Cursor; Right : String) return Boolean
                             renames Maps.Equivalent_Keys;
   function Equivalent_Keys (Left : String; Right : Cursor) return Boolean
                             renames Maps.Equivalent_Keys;
   function Copy (Source : Maps.Map; Capacity : in Ada.Containers.Count_Type) return Maps.Map
     renames Maps.Copy;

   --  ------------------------------
   --  Map Bean
   --  ------------------------------
   --  The Map_Bean is a map of objects that also exposes the Bean interface.
   --  This allows the map to be available and accessed from an Object instance.
   type Map_Bean is new Maps.Map and Util.Beans.Basic.Bean with private;
   type Map_Bean_Access is access all Map_Bean'Class;

   --  Get the value identified by the name.
   --  If the name cannot be found, the method should return the Null object.
   function Get_Value (From : in Map_Bean;
                       Name : in String) return Object;

   --  Set the value identified by the name.
   --  If the map contains the given name, the value changed.
   --  Otherwise name is added to the map and the value associated with it.
   procedure Set_Value (From  : in out Map_Bean;
                        Name  : in String;
                        Value : in Object);

   --  Create an object that contains a <tt>Map_Bean</tt> instance.
   function Create return Object;

   --  Iterate over the members of the map.
   procedure Iterate (From    : in Object;
                      Process : not null access procedure (Name : in String;
                                                           Item : in Object));

private

   type Map_Bean is new Maps.Map and Util.Beans.Basic.Bean with null record;

end Util.Beans.Objects.Maps;

-----------------------------------------------------------------------
--  util-beans-objects-maps -- Object maps
--  Copyright (C) 2010, 2011, 2012, 2017, 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings.Hash;
with Util.Beans.Basic;
package Util.Beans.Objects.Maps is

   package Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type        => String,
                                                Element_Type    => Object,
                                                Hash            => Ada.Strings.Hash,
                                                Equivalent_Keys => "=");

   subtype Cursor is Maps.Cursor;
   subtype Map is Maps.Map;

   --  Make all the Maps operations available (a kind of 'use Maps' for anybody).
   function Length (Container : in Map) return Ada.Containers.Count_Type renames Maps.Length;
   function Is_Empty (Container : in Map) return Boolean renames Maps.Is_Empty;
   procedure Clear (Container : in out Map) renames Maps.Clear;
   function Key (Position : Cursor) return String renames Maps.Key;

   procedure Include (Container : in out Map;
                      Key : in String;
                      New_Item : in Object) renames Maps.Include;
   procedure Query_Element (Position : in Cursor;
                            Process  : not null access procedure (Key     : String;
                                                                  Element : Object))
                            renames Maps.Query_Element;

   function Has_Element (Position : Cursor) return Boolean renames Maps.Has_Element;
   function Element (Position : Cursor) return Object renames Maps.Element;
   procedure Next (Position : in out Cursor) renames Maps.Next;
   function Next (Position : Cursor) return Cursor renames Maps.Next;
   function Equivalent_Keys (Left, Right : Cursor) return Boolean renames Maps.Equivalent_Keys;
   function Equivalent_Keys (Left : Cursor; Right : String) return Boolean
                             renames Maps.Equivalent_Keys;
   function Equivalent_Keys (Left : String; Right : Cursor) return Boolean
                             renames Maps.Equivalent_Keys;
   function Copy (Source : Maps.Map; Capacity : in Ada.Containers.Count_Type) return Maps.Map
     renames Maps.Copy;

   --  ------------------------------
   --  Map Bean
   --  ------------------------------
   --  The Map_Bean is a map of objects that also exposes the Bean interface.
   --  This allows the map to be available and accessed from an Object instance.
   type Map_Bean is new Maps.Map and Util.Beans.Basic.Bean with private;
   type Map_Bean_Access is access all Map_Bean'Class;

   --  Get the value identified by the name.
   --  If the name cannot be found, the method should return the Null object.
   function Get_Value (From : in Map_Bean;
                       Name : in String) return Object;

   --  Set the value identified by the name.
   --  If the map contains the given name, the value changed.
   --  Otherwise name is added to the map and the value associated with it.
   procedure Set_Value (From  : in out Map_Bean;
                        Name  : in String;
                        Value : in Object);

   --  Create an object that contains a <tt>Map_Bean</tt> instance.
   function Create return Object;

   --  Iterate over the members of the map.
   procedure Iterate (From    : in Object;
                      Process : not null access procedure (Name : in String;
                                                           Item : in Object));

private

   type Map_Bean is new Maps.Map and Util.Beans.Basic.Bean with null record;

end Util.Beans.Objects.Maps;

Fix header style

Fix header style


-----------------------------------------------------------------------
--  wiki-filters-collectors -- Wiki word and link collectors
--  Copyright (C) 2016 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

package body Wiki.Filters.Collectors is

   procedure Add_String (Into : in out WString_Maps.Map;
                         Item : in Wiki.Strings.WString);

   procedure Add_String (Into : in out WString_Maps.Map;
                         Item : in Wiki.Strings.WString) is

      procedure Increment (Key : in Wiki.Strings.WString;
                           Value : in out Natural);

      procedure Increment (Key : in Wiki.Strings.WString;
                           Value : in out Natural) is
         pragma Unreferenced (Key);
      begin
         Value := Value + 1;
      end Increment;

      Pos : constant WString_Maps.Cursor := Into.Find (Item);
   begin
      if WString_Maps.Has_Element (Pos) then
         Into.Update_Element (Pos, Increment'Access);
      else
         Into.Insert (Item, 1);
      end if;
   end Add_String;

   function Find (Map  : in Collector_Type;
                  Item : in Wiki.Strings.WString) return Cursor is
   begin
      return Map.Items.Find (Item);
   end Find;

   function Contains (Map  : in Collector_Type;
                      Item : in Wiki.Strings.WString) return Boolean is
   begin
      return Map.Items.Contains (Item);
   end Contains;

   procedure Iterate (Map : in Collector_Type;
                      Process : not null access procedure (Pos : in Cursor)) is
   begin
      Map.Items.Iterate (Process);
   end Iterate;

   --  ------------------------------
   --  Word Collector type
   --  ------------------------------
   procedure Collect_Words (Filter  : in out Word_Collector_Type;
                            Content : in Wiki.Strings.WString) is
      Pos   : Natural := Content'First;
      Start : Natural := Content'First;
      C     : Wiki.Strings.WChar;
   begin
      while Pos <= Content'Last loop
         C := Content (Pos);
         if Wiki.Strings.Is_Alphanumeric (C) then
            null;
         else
            if Start + 1 < Pos - 1 then
               Add_String (Filter.Items, Content (Start .. Pos - 1));
            end if;
            Start := Pos + 1;
         end if;
         Pos := Pos + 1;
      end loop;
      if Start < Content'Last then
         Add_String (Filter.Items, Content (Start .. Content'Last));
      end if;
   end Collect_Words;

   --  ------------------------------
   --  Add a text content with the given format to the document.
   --  ------------------------------
   procedure Add_Text (Filter    : in out Word_Collector_Type;
                       Document  : in out Wiki.Documents.Document;
                       Text      : in Wiki.Strings.WString;
                       Format    : in Wiki.Format_Map) is
   begin
      Filter.Collect_Words (Text);
      Filter_Type (Filter).Add_Text (Document, Text, Format);
   end Add_Text;

   --  ------------------------------
   --  Add a section header with the given level in the document.
   --  ------------------------------
   procedure Add_Header (Filter    : in out Word_Collector_Type;
                         Document  : in out Wiki.Documents.Document;
                         Header    : in Wiki.Strings.WString;
                         Level     : in Natural) is
   begin
      Filter.Collect_Words (Header);
      Filter_Type (Filter).Add_Header (Document, Header, Level);
   end Add_Header;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   procedure Add_Link (Filter     : in out Word_Collector_Type;
                       Document   : in out Wiki.Documents.Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Link (Document, Name, Attributes);
   end Add_Link;

   --  ------------------------------
   --  Add an image.
   --  ------------------------------
   procedure Add_Image (Filter     : in out Word_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Image (Document, Name, Attributes);
   end Add_Image;

   --  ------------------------------
   --  Add a quote.
   --  ------------------------------
   procedure Add_Quote (Filter     : in out Word_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Quote (Document, Name, Attributes);
   end Add_Quote;

   --  ------------------------------
   --  Add a text block that is pre-formatted.
   --  ------------------------------
   procedure Add_Preformatted (Filter   : in out Word_Collector_Type;
                               Document : in out Wiki.Documents.Document;
                               Text     : in Wiki.Strings.WString;
                               Format   : in Wiki.Strings.WString) is
   begin
      Filter.Collect_Words (Text);
      Filter_Type (Filter).Add_Preformatted (Document, Text, Format);
   end Add_Preformatted;

   procedure Collect_Link (Filter     : in out Link_Collector_Type;
                           Attributes : in Wiki.Attributes.Attribute_List;
                           Name       : in String) is
      Href : constant Wiki.Strings.WString := Wiki.Attributes.Get_Attribute (Attributes, Name);
   begin
      if Href'Length > 0 then
         Add_String (Filter.Items, Href);
      end if;
   end Collect_Link;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   overriding
   procedure Add_Link (Filter     : in out Link_Collector_Type;
                       Document   : in out Wiki.Documents.Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Collect_Link (Filter, Attributes, "href");
      Filter_Type (Filter).Add_Link (Document, Name, Attributes);
   end Add_Link;

   --  ------------------------------
   --  Push a HTML node with the given tag to the document.
   --  ------------------------------
   overriding
   procedure Push_Node (Filter     : in out Link_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Tag        : in Wiki.Html_Tag;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      if Tag = A_TAG then
         Collect_Link (Filter, Attributes, "href");
      end if;
      Filter_Type (Filter).Push_Node (Document, Tag, Attributes);
   end Push_Node;

end Wiki.Filters.Collectors;

-----------------------------------------------------------------------
--  wiki-filters-collectors -- Wiki word and link collectors
--  Copyright (C) 2016 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

package body Wiki.Filters.Collectors is

   procedure Add_String (Into : in out WString_Maps.Map;
                         Item : in Wiki.Strings.WString);

   procedure Add_String (Into : in out WString_Maps.Map;
                         Item : in Wiki.Strings.WString) is

      procedure Increment (Key : in Wiki.Strings.WString;
                           Value : in out Natural);

      procedure Increment (Key : in Wiki.Strings.WString;
                           Value : in out Natural) is
         pragma Unreferenced (Key);
      begin
         Value := Value + 1;
      end Increment;

      Pos : constant WString_Maps.Cursor := Into.Find (Item);
   begin
      if WString_Maps.Has_Element (Pos) then
         Into.Update_Element (Pos, Increment'Access);
      else
         Into.Insert (Item, 1);
      end if;
   end Add_String;

   function Find (Map  : in Collector_Type;
                  Item : in Wiki.Strings.WString) return Cursor is
   begin
      return Map.Items.Find (Item);
   end Find;

   function Contains (Map  : in Collector_Type;
                      Item : in Wiki.Strings.WString) return Boolean is
   begin
      return Map.Items.Contains (Item);
   end Contains;

   procedure Iterate (Map : in Collector_Type;
                      Process : not null access procedure (Pos : in Cursor)) is
   begin
      Map.Items.Iterate (Process);
   end Iterate;

   --  ------------------------------
   --  Word Collector type
   --  ------------------------------
   procedure Collect_Words (Filter  : in out Word_Collector_Type;
                            Content : in Wiki.Strings.WString) is
      Pos   : Natural := Content'First;
      Start : Natural := Content'First;
      C     : Wiki.Strings.WChar;
   begin
      while Pos <= Content'Last loop
         C := Content (Pos);
         if Wiki.Strings.Is_Alphanumeric (C) then
            null;
         else
            if Start + 1 < Pos - 1 then
               Add_String (Filter.Items, Content (Start .. Pos - 1));
            end if;
            Start := Pos + 1;
         end if;
         Pos := Pos + 1;
      end loop;
      if Start < Content'Last then
         Add_String (Filter.Items, Content (Start .. Content'Last));
      end if;
   end Collect_Words;

   --  ------------------------------
   --  Add a text content with the given format to the document.
   --  ------------------------------
   procedure Add_Text (Filter    : in out Word_Collector_Type;
                       Document  : in out Wiki.Documents.Document;
                       Text      : in Wiki.Strings.WString;
                       Format    : in Wiki.Format_Map) is
   begin
      Filter.Collect_Words (Text);
      Filter_Type (Filter).Add_Text (Document, Text, Format);
   end Add_Text;

   --  ------------------------------
   --  Add a section header with the given level in the document.
   --  ------------------------------
   procedure Add_Header (Filter    : in out Word_Collector_Type;
                         Document  : in out Wiki.Documents.Document;
                         Header    : in Wiki.Strings.WString;
                         Level     : in Natural) is
   begin
      Filter.Collect_Words (Header);
      Filter_Type (Filter).Add_Header (Document, Header, Level);
   end Add_Header;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   procedure Add_Link (Filter     : in out Word_Collector_Type;
                       Document   : in out Wiki.Documents.Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Link (Document, Name, Attributes);
   end Add_Link;

   --  ------------------------------
   --  Add an image.
   --  ------------------------------
   procedure Add_Image (Filter     : in out Word_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Image (Document, Name, Attributes);
   end Add_Image;

   --  ------------------------------
   --  Add a quote.
   --  ------------------------------
   procedure Add_Quote (Filter     : in out Word_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Filter_Type (Filter).Add_Quote (Document, Name, Attributes);
   end Add_Quote;

   --  ------------------------------
   --  Add a text block that is pre-formatted.
   --  ------------------------------
   procedure Add_Preformatted (Filter   : in out Word_Collector_Type;
                               Document : in out Wiki.Documents.Document;
                               Text     : in Wiki.Strings.WString;
                               Format   : in Wiki.Strings.WString) is
   begin
      Filter.Collect_Words (Text);
      Filter_Type (Filter).Add_Preformatted (Document, Text, Format);
   end Add_Preformatted;

   procedure Collect_Link (Filter     : in out Link_Collector_Type;
                           Attributes : in Wiki.Attributes.Attribute_List;
                           Name       : in String) is
      Href : constant Wiki.Strings.WString := Wiki.Attributes.Get_Attribute (Attributes, Name);
   begin
      if Href'Length > 0 then
         Add_String (Filter.Items, Href);
      end if;
   end Collect_Link;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   overriding
   procedure Add_Link (Filter     : in out Link_Collector_Type;
                       Document   : in out Wiki.Documents.Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Collect_Link (Filter, Attributes, "href");
      Filter_Type (Filter).Add_Link (Document, Name, Attributes);
   end Add_Link;

   --  ------------------------------
   --  Push a HTML node with the given tag to the document.
   --  ------------------------------
   overriding
   procedure Push_Node (Filter     : in out Link_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Tag        : in Wiki.Html_Tag;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      if Tag = A_TAG then
         Collect_Link (Filter, Attributes, "href");
      end if;
      Filter_Type (Filter).Push_Node (Document, Tag, Attributes);
   end Push_Node;

   --  ------------------------------
   --  Add an image.
   --  ------------------------------
   overriding
   procedure Add_Image (Filter     : in out Image_Collector_Type;
                        Document   : in out Wiki.Documents.Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
      Src : constant Wiki.Strings.WString := Wiki.Attributes.Get_Attribute (Attributes, "src");
   begin
      Add_String (Filter.Items, Src);
      Filter_Type (Filter).Add_Image (Document, Name, Attributes);
   end Add_Image;

end Wiki.Filters.Collectors;

Implement Add_Image to collect images used in a wiki text


with C_String;
with Interfaces.C;
with POSIX.C_Types;
with System;

package body POSIX.Directory is

  --
  -- Change_By_Descriptor.
  --

  procedure Change_By_Descriptor
    (Descriptor  : in     File.Valid_Descriptor_t;
     Error_Value :    out Error.Error_t)
  is
    function Fchdir (Descriptor : in File.Valid_Descriptor_t)
      return Error.Return_Value_t;
    pragma Import (C, Fchdir, "fchdir");
  begin
    if Fchdir (Descriptor) = -1 then
      Error_Value := Error.Get_Error;
    else
      Error_Value := Error.Error_None;
    end if;
  end Change_By_Descriptor;

  --
  -- Change_By_Name.
  --

  procedure Change_By_Name
    (Name        : in     String;
     Error_Value :    out Error.Error_t)
  is
    Descriptor   : File.Descriptor_t;
    Error_Local  : Error.Error_t;
  begin
    File.Open_Read_Only
      (File_Name    => Name,
       Non_Blocking => False,
       Descriptor   => Descriptor,
       Error_Value  => Error_Local);
    if Error_Local = Error.Error_None then
      Change_By_Descriptor
        (Descriptor  => Descriptor,
         Error_Value => Error_Value);
      File.Close
        (Descriptor  => Descriptor,
         Error_Value => Error_Local);
      if Error_Local /= Error.Error_None then
        Error_Value := Error_Local;
      end if;
    else
      Error_Value := Error_Local;
    end if;
  end Change_By_Name;

  --
  -- Create directory.
  --

  function Create_Boundary
    (Name : in String;
     Mode : in Permissions.Mode_t) return Error.Return_Value_t
    --# global in Errno.Errno_Value;
    --# return R =>
    --#  ((R = 0)  -> (Error.Get_Error (Errno.Errno_Value)  = Error.Error_None)) or
    --#  ((R = -1) -> (Error.Get_Error (Errno.Errno_Value) /= Error.Error_None));
    --# hide Create_Boundary
  is
    C_Name : aliased Interfaces.C.char_array := Interfaces.C.To_C (Name);

    function Mkdir
      (Name : in C_String.String_Not_Null_Ptr_t;
       Mode : in Permissions.Mode_t) return Error.Return_Value_t;
    pragma Import (C, Mkdir, "mkdir");
  begin
    return Mkdir
      (Name => C_String.To_C_String (C_Name'Unchecked_Access),
       Mode => Mode);
  end Create_Boundary;

  procedure Create
    (Name        : in     String;
     Mode        : in     Permissions.Mode_t;
     Error_Value :    out Error.Error_t) is
  begin
    case Create_Boundary (Name, Mode) is
      when  0 => Error_Value := Error.Error_None;
      when -1 => Error_Value := Error.Get_Error;
    end case;
  end Create;

  --
  -- Remove empty directory.
  --

  function Remove_Boundary (Name : in String) return Error.Return_Value_t
    --# global in Errno.Errno_Value;
    --# return R =>
    --#  ((R = 0)  -> (Error.Get_Error (Errno.Errno_Value)  = Error.Error_None)) or
    --#  ((R = -1) -> (Error.Get_Error (Errno.Errno_Value) /= Error.Error_None));
    --# hide Remove_Boundary
  is
    C_Name : aliased Interfaces.C.char_array := Interfaces.C.To_C (Name);

    function Rmdir (Name : in C_String.String_Not_Null_Ptr_t)
      return Error.Return_Value_t;
    pragma Import (C, Rmdir, "rmdir");
  begin
    return Rmdir (C_String.To_C_String (C_Name'Unchecked_Access));
  end Remove_Boundary;

  procedure Remove
    (Name        : in     String;
     Error_Value :    out Error.Error_t) is
  begin
    case Remove_Boundary (Name) is
      when  0 => Error_Value := Error.Error_None;
      when -1 => Error_Value := Error.Get_Error;
    end case;
  end Remove;

  --
  -- Retrieve current working directory.
  --

  procedure Get_Current_Boundary
    (Name        :    out Path.Path_Name_t;
     Name_Size   :    out Path.Path_Name_Size_t;
     Error_Value :    out Error.Error_t)
    --# hide Get_Current_Boundary
  is
    use type C_String.String_Ptr_t;

    function Getcwd
      (Buffer : System.Address;
       Size   : C_Types.Size_t) return C_String.String_Ptr_t;
    pragma Import (C, Getcwd, "getcwd");

    Pointer : C_String.String_Ptr_t;
  begin
    Pointer := Getcwd
      (Buffer => Name (Name'First)'Address,
       Size   => C_Types.Size_t (Path.Path_Name_Index_t'Last));

    if Pointer = null then
      Error_Value := Error.Get_Error;
      Name_Size   := 0;
    else
      Error_Value := Error.Error_None;
      Name_Size   := Path.Path_Name_Size_t (C_String.Length (Pointer));
    end if;
  end Get_Current_Boundary;

  procedure Get_Current
    (Name        :    out Path.Path_Name_t;
     Name_Size   :    out Path.Path_Name_Size_t;
     Error_Value :    out Error.Error_t) is
  begin
    Get_Current_Boundary
      (Name        => Name,
       Name_Size   => Name_Size,
       Error_Value => Error_Value);
  end Get_Current;

end POSIX.Directory;

with C_String;
with Interfaces.C;
with POSIX.C_Types;
with System;

package body POSIX.Directory is

  --
  -- Change_By_Descriptor.
  --

  procedure Change_By_Descriptor
    (Descriptor  : in     File.Valid_Descriptor_t;
     Error_Value :    out Error.Error_t)
  is
    function Fchdir (Descriptor : in File.Valid_Descriptor_t)
      return Error.Return_Value_t;
    pragma Import (C, Fchdir, "fchdir");
  begin
    if Fchdir (Descriptor) = -1 then
      Error_Value := Error.Get_Error;
    else
      Error_Value := Error.Error_None;
    end if;
  end Change_By_Descriptor;

  --
  -- Change_By_Name.
  --

  procedure Change_By_Name
    (Name        : in     String;
     Error_Value :    out Error.Error_t)
  is
    Descriptor   : File.Descriptor_t;
    Error_Local  : Error.Error_t;
  begin
    File.Open_Read_Only
      (File_Name    => Name,
       Non_Blocking => False,
       Descriptor   => Descriptor,
       Error_Value  => Error_Local);
    if Error_Local = Error.Error_None then
      Change_By_Descriptor
        (Descriptor  => Descriptor,
         Error_Value => Error_Value);
      File.Close
        (Descriptor  => Descriptor,
         Error_Value => Error_Local);
      if Error_Local /= Error.Error_None then
        Error_Value := Error_Local;
      end if;
    else
      Error_Value := Error_Local;
    end if;
  end Change_By_Name;

  --
  -- Create directory.
  --

  function Create_Boundary
    (Name : in String;
     Mode : in Permissions.Mode_t) return Error.Return_Value_t
    --# global in Errno.Errno_Value;
    --# return R =>
    --#  ((R = 0)  -> (Error.Get_Error (Errno.Errno_Value)  = Error.Error_None)) or
    --#  ((R = -1) -> (Error.Get_Error (Errno.Errno_Value) /= Error.Error_None));
  is
    --# hide Create_Boundary

    C_Name : aliased Interfaces.C.char_array := Interfaces.C.To_C (Name);

    function Mkdir
      (Name : in C_String.String_Not_Null_Ptr_t;
       Mode : in Permissions.Mode_t) return Error.Return_Value_t;
    pragma Import (C, Mkdir, "mkdir");
  begin
    return Mkdir
      (Name => C_String.To_C_String (C_Name'Unchecked_Access),
       Mode => Mode);
  end Create_Boundary;

  procedure Create
    (Name        : in     String;
     Mode        : in     Permissions.Mode_t;
     Error_Value :    out Error.Error_t) is
  begin
    case Create_Boundary (Name, Mode) is
      when  0 => Error_Value := Error.Error_None;
      when -1 => Error_Value := Error.Get_Error;
    end case;
  end Create;

  --
  -- Remove empty directory.
  --

  function Remove_Boundary (Name : in String) return Error.Return_Value_t
    --# global in Errno.Errno_Value;
    --# return R =>
    --#  ((R = 0)  -> (Error.Get_Error (Errno.Errno_Value)  = Error.Error_None)) or
    --#  ((R = -1) -> (Error.Get_Error (Errno.Errno_Value) /= Error.Error_None));
  is
    --# hide Remove_Boundary

    C_Name : aliased Interfaces.C.char_array := Interfaces.C.To_C (Name);

    function Rmdir (Name : in C_String.String_Not_Null_Ptr_t)
      return Error.Return_Value_t;
    pragma Import (C, Rmdir, "rmdir");
  begin
    return Rmdir (C_String.To_C_String (C_Name'Unchecked_Access));
  end Remove_Boundary;

  procedure Remove
    (Name        : in     String;
     Error_Value :    out Error.Error_t) is
  begin
    case Remove_Boundary (Name) is
      when  0 => Error_Value := Error.Error_None;
      when -1 => Error_Value := Error.Get_Error;
    end case;
  end Remove;

  --
  -- Retrieve current working directory.
  --

  procedure Get_Current_Boundary
    (Name        :    out Path.Path_Name_t;
     Name_Size   :    out Path.Path_Name_Size_t;
     Error_Value :    out Error.Error_t)
    --# global in Errno.Errno_Value;
    --# derives Name, Name_Size, Error_Value from Errno.Errno_Value;
  is
    --# hide Get_Current_Boundary

    use type C_String.String_Ptr_t;

    function Getcwd
      (Buffer : System.Address;
       Size   : C_Types.Size_t) return C_String.String_Ptr_t;
    pragma Import (C, Getcwd, "getcwd");

    Pointer : C_String.String_Ptr_t;
  begin
    Pointer := Getcwd
      (Buffer => Name (Name'First)'Address,
       Size   => C_Types.Size_t (Path.Path_Name_Index_t'Last));

    if Pointer = null then
      Error_Value := Error.Get_Error;
      Name_Size   := 0;
    else
      Error_Value := Error.Error_None;
      Name_Size   := Path.Path_Name_Size_t (C_String.Length (Pointer));
    end if;
  end Get_Current_Boundary;

  procedure Get_Current
    (Name        :    out Path.Path_Name_t;
     Name_Size   :    out Path.Path_Name_Size_t;
     Error_Value :    out Error.Error_t) is
  begin
    Get_Current_Boundary
      (Name        => Name,
       Name_Size   => Name_Size,
       Error_Value => Error_Value);
  end Get_Current;

end POSIX.Directory;

Update directory package for SPARK.

Update directory package for SPARK.


-----------------------------------------------------------------------
--  util-commands-parsers -- Support to parse command line options
--  Copyright (C) 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

--  === Command line parsers ===
--  Parsing command line arguments before their execution is handled by the
--  `Config_Parser` generic package.  This allows to customize how the arguments are
--  parsed.
--
--  The `Util.Commands.Parsers.No_Parser` package can be used to execute the command
--  without parsing its arguments.
--
--  The `Util.Commands.Parsers.GNAT_Parser.Config_Parser` package provides support to
--  parse command line arguments by using the `GNAT` `Getopt` support.
package Util.Commands.Parsers is

   --  The config parser that must be instantiated to provide the configuration type
   --  and the Execute procedure that will parse the arguments before executing the command.
   generic
      type Config_Type is limited private;
      with procedure Execute (Config  : in out Config_Type;
                              Args    : in Argument_List'Class;
                              Process : not null access
                                procedure (Cmd_Args : in Argument_List'Class)) is <>;
   package Config_Parser is
   end Config_Parser;

   --  The empty parser.
   type No_Config_Type is limited null record;

   --  Execute the command with its arguments (no parsing).
   procedure Execute (Config : in out No_Config_Type;
                      Args   : in Argument_List'Class;
                      Process : not null access
                                procedure (Cmd_Args : in Argument_List'Class));

   --  A parser that executes the command immediately (no parsing of arguments).
   package No_Parser is
     new Config_Parser (Config_Type => No_Config_Type,
                        Execute     => Execute);

end Util.Commands.Parsers;

-----------------------------------------------------------------------
--  util-commands-parsers -- Support to parse command line options
--  Copyright (C) 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

--  === Command line parsers ===
--  Parsing command line arguments before their execution is handled by the
--  `Config_Parser` generic package.  This allows to customize how the arguments are
--  parsed.
--
--  The `Util.Commands.Parsers.No_Parser` package can be used to execute the command
--  without parsing its arguments.
--
--  The `Util.Commands.Parsers.GNAT_Parser.Config_Parser` package provides support to
--  parse command line arguments by using the `GNAT` `Getopt` support.
package Util.Commands.Parsers is

   --  The config parser that must be instantiated to provide the configuration type
   --  and the Execute procedure that will parse the arguments before executing the command.
   generic
      type Config_Type is limited private;
      with procedure Execute (Config  : in out Config_Type;
                              Args    : in Argument_List'Class;
                              Process : not null access
                                procedure (Cmd_Args : in Argument_List'Class)) is <>;
      with procedure Usage (Name   : in String;
                            Config : in out Config_Type) is <>;
   package Config_Parser is
   end Config_Parser;

   --  The empty parser.
   type No_Config_Type is limited null record;

   --  Execute the command with its arguments (no parsing).
   procedure Execute (Config : in out No_Config_Type;
                      Args   : in Argument_List'Class;
                      Process : not null access
                                procedure (Cmd_Args : in Argument_List'Class));

   procedure Usage (Name   : in String;
                    Config : in out No_Config_Type) is null;

   --  A parser that executes the command immediately (no parsing of arguments).
   package No_Parser is
     new Config_Parser (Config_Type => No_Config_Type,
                        Execute     => Execute,
                        Usage       => Usage);

end Util.Commands.Parsers;

Add a Usage procedure to the Config_Parser