--  Warning: This file is automatically generated by AFLEX.
--           It is useless to modify it. Change the ".Y" & ".L" files instead.
--  Template: templates/body-reentrant-io.adb
package body ${NAME}_IO is

   --  gets input and stuffs it into 'buf'.  number of characters read, or YY_NULL,
   --  is returned in 'result'.

   procedure YY_INPUT (Context  : in out Context_Type;
                       buf      : out unbounded_character_array;
                       result   : out Integer;
                       max_size : in Integer) is
      c   : Character;
      i   : Integer := 1;
      loc : Integer := buf'First;
%if error
   --    Since buf is an out parameter which is not readable
   --    and saved lines is a string pointer which space must
   --    be allocated after we know the size, we maintain
   --    an extra buffer to collect the input line and
   --    save it into the saved line 2.
      Temp_Line : String (1 .. YY_BUF_SIZE + 2);
%end
   begin
%if error
      -- buf := ( others => ASCII.NUL ); -- CvdL: does not work in GNAT
      for j in buf'First .. buf'Last loop
         buf (j) := ASCII.NUL;
      end loop;
      -- Move the saved lines forward.
      Context.Saved_Tok_Line1 := Context.Saved_Tok_Line2;
      Context.Line_Number_Of_Saved_Tok_Line1 := Context.Line_Number_Of_Saved_Tok_Line2;

%end
      if Ada.Text_IO.Is_Open (Context.user_input_file) then
         while i <= max_size loop
            --  Ada ate our newline, put it back on the end.
            if Ada.Text_IO.End_Of_Line (Context.user_input_file) then
               buf (loc) := ASCII.LF;
               Ada.Text_IO.Skip_Line (Context.user_input_file, 1);
%if error
               --   We try to get one line by one line. So we return
               --   here because we saw the end_of_line.
               result := i;
               Temp_Line (i) := ASCII.LF;
               Context.Saved_Tok_Line2 := new String (1 .. i);
               Context.Saved_Tok_Line2 (1 .. i) := Temp_Line (1 .. i);
               Context.Line_Number_Of_Saved_Tok_Line2 := Context.Line_Number_Of_Saved_Tok_Line1 + 1;
               return;
%end
%if interactive
               i := i + 1; --  update counter, miss end of loop
               exit; --  in interactive mode return at end of line.
%end
            else
               --  UCI CODES CHANGED:
               --    The following codes are modified. Previous codes is commented out.
               --    The purpose of doing this is to make it possible to set Temp_Line
               --    in Ayacc-extension specific codes. Definitely, we can read the character
               --    into the Temp_Line and then set the buf. But Temp_Line will only
               --    be used in Ayacc-extension specific codes which makes
               --    this approach impossible.
               Ada.Text_IO.Get (Context.user_input_file, c);
               buf (loc) := c;
--             Ada.Text_IO.Get (Context.user_input_file, buf (loc));
%if error
               Temp_Line (i) := c;
%end
            end if;

            loc := loc + 1;
            i := i + 1;
         end loop;
      else
         while i <= max_size loop
            if Ada.Text_IO.End_Of_Line then -- Ada ate our newline, put it back on the end.
               buf (loc) := ASCII.LF;
               Ada.Text_IO.Skip_Line (1);
%if error
               --   We try to get one line by one line. So we return
               --   here because we saw the end_of_line.
               result := i;
               Temp_Line (i) := ASCII.LF;
               Context.Saved_Tok_Line2 := new String (1 .. i);
               Context.Saved_Tok_Line2 (1 .. i) := Temp_Line (1 .. i);
               Context.Line_Number_Of_Saved_Tok_Line2 := Context.Line_Number_Of_Saved_Tok_Line1 + 1;
               return;
%end

            else
               --  The following codes are modified. Previous codes is commented out.
               --  The purpose of doing this is to make it possible to set Temp_Line
               --  in Ayacc-extension specific codes. Definitely, we can read the character
               --  into the Temp_Line and then set the buf. But Temp_Line will only
               --  be used in Ayacc-extension specific codes which makes this approach impossible.
               Ada.Text_IO.Get (c);
               buf (loc) := c;
%if error
               Temp_Line (i) := c;
%end
            end if;

            loc := loc + 1;
            i := i + 1;
         end loop;
      end if; --  for input file being standard input
      result := i - 1;

%if error
      --  Since we get one line by one line, if we
      --  reach here, it means that current line have
      --  more that max_size characters. So it is
      --  impossible to hold the whole line. We
      --  report the warning message and continue.
      buf (loc - 1) := Ascii.LF;
      if Ada.Text_IO.Is_Open (Context.user_input_file) then
         Ada.Text_IO.Skip_Line (Context.user_input_file, 1);
      else
         Ada.Text_IO.Skip_Line (1);
      end if;
      Temp_Line (i - 1) := ASCII.LF;
      Context.Saved_Tok_Line2 := new String (1 .. i - 1);
      Context.Saved_Tok_Line2 (1 .. i - 1) := Temp_Line (1 .. i - 1);
      Context.Line_Number_Of_Saved_Tok_Line2 := Context.Line_Number_Of_Saved_Tok_Line1 + 1;
      Put_Line ("Input line "
                & Integer'Image ( Context.Line_Number_Of_Saved_Tok_Line2 )
                & "has more than "
                & Integer'Image ( max_size )
                & " characters, ... truncated." );
%end
   exception
      when Ada.Text_IO.End_Error =>
         result := i - 1;
         --  when we hit EOF we need to set yy_eof_has_been_seen
         Context.yy_eof_has_been_seen := True;
%if error
         --   Processing incomplete line.
         if i /= 1 then
            -- Current line is not empty but do not have end_of_line.
            -- So current line is incomplete line. But we still need
            -- to save it.
            Context.Saved_Tok_Line2 := new String (1 .. i - 1);
            Context.Saved_Tok_Line2 (1 .. i - 1) := Temp_Line (1 .. i - 1);
            Context.Line_Number_Of_Saved_Tok_Line2 := Context.Line_Number_Of_Saved_Tok_Line1 + 1;
         end if;
%end
   end YY_INPUT;

   --  yy_get_next_buffer - try to read in new buffer
   --
   --  returns a code representing an action
   --     EOB_ACT_LAST_MATCH -
   --     EOB_ACT_RESTART_SCAN - restart the scanner
   --     EOB_ACT_END_OF_FILE - end of file

   function yy_get_next_buffer (Context : in out Context_Type) return eob_action_type is
      dest           : Integer := 0;
      source         : Integer := Context.dfa.yytext_ptr - 1; -- copy prev. char, too
      number_to_move : Integer;
      ret_val        : eob_action_type;
      num_to_read    : Integer;
   begin
      if Context.dfa.yy_c_buf_p > Context.yy_n_chars + 1 then
         raise NULL_IN_INPUT;
      end if;

      --  try to read more data

      --  first move last chars to start of buffer
      number_to_move := Context.dfa.yy_c_buf_p - Context.dfa.yytext_ptr;

      for i in 0 .. number_to_move - 1 loop
         Context.dfa.yy_ch_buf (dest) := Context.dfa.yy_ch_buf (source);
         dest := dest + 1;
         source := source + 1;
      end loop;

      if Context.yy_eof_has_been_seen then
         --  don't do the read, it's not guaranteed to return an EOF,
         --  just force an EOF

         Context.yy_n_chars := 0;
      else
         num_to_read := YY_BUF_SIZE - number_to_move - 1;

         if num_to_read > YY_READ_BUF_SIZE then
            num_to_read := YY_READ_BUF_SIZE;
         end if;

         --  read in more data
         YY_INPUT (Context,
                   Context.dfa.yy_ch_buf (number_to_move .. Context.dfa.yy_ch_buf'Last),
                   Context.yy_n_chars, num_to_read);
      end if;
      if Context.yy_n_chars = 0 then
         if number_to_move = 1 then
            ret_val := EOB_ACT_END_OF_FILE;
         else
            ret_val := EOB_ACT_LAST_MATCH;
         end if;

         Context.yy_eof_has_been_seen := True;
      else
         ret_val := EOB_ACT_RESTART_SCAN;
      end if;

      Context.yy_n_chars := Context.yy_n_chars + number_to_move;
      Context.dfa.yy_ch_buf (Context.yy_n_chars) := YY_END_OF_BUFFER_CHAR;
      Context.dfa.yy_ch_buf (Context.yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;

      --  yytext begins at the second character in
      --  yy_ch_buf; the first character is the one which
      --  preceded it before reading in the latest buffer;
      --  it needs to be kept around in case it's a
      --  newline, so yy_get_previous_state() will have
      --  with '^' rules active

      Context.dfa.yytext_ptr := 1;

      return ret_val;
   end yy_get_next_buffer;

%if unput
   procedure yyUnput (Context : in out Context_Type;
                      c : Character; yy_bp : in out Integer) is
      number_to_move : Integer;
      dest : Integer;
      source : Integer;
      tmp_yy_cp : Integer;
   begin
      tmp_yy_cp := Context.dfa.yy_c_buf_p;
      --  undo effects of setting up yytext
      Context.dfa.yy_ch_buf (tmp_yy_cp) := Context.dfa.yy_hold_char;

      if tmp_yy_cp < 2 then
         --  need to shift things up to make room
         number_to_move := Context.yy_n_chars + 2; --  +2 for EOB chars
         dest := YY_BUF_SIZE + 2;
         source := number_to_move;

         while source > 0 loop
            dest := dest - 1;
            source := source - 1;
            Context.dfa.yy_ch_buf (dest) := Context.dfa.yy_ch_buf (source);
         end loop;

         tmp_yy_cp := tmp_yy_cp + dest - source;
         Context.dfa.yy_bp := Context.dfa.yy_bp + dest - source;
         Context.yy_n_chars := YY_BUF_SIZE;

         if tmp_yy_cp < 2 then
            raise PUSHBACK_OVERFLOW;
         end if;
      end if;

      if tmp_yy_cp > yy_bp
        and then Context.dfa.yy_ch_buf (tmp_yy_cp - 1) = ASCII.LF
      then
         Context.dfa.yy_ch_buf (tmp_yy_cp - 2) := ASCII.LF;
      end if;

      tmp_yy_cp := tmp_yy_cp - 1;
      Context.dfa.yy_ch_buf (tmp_yy_cp) := c;

      --  Note:  this code is the text of YY_DO_BEFORE_ACTION, only
      --         here we get different yy_cp and yy_bp's
      Context.dfa.yytext_ptr := Context.dfa.yy_bp;
      Context.dfa.yy_hold_char := Context.dfa.yy_ch_buf (tmp_yy_cp);
      Context.dfa.yy_ch_buf (tmp_yy_cp) := ASCII.NUL;
      Context.dfa.yy_c_buf_p := tmp_yy_cp;
   end yyUnput;

   procedure Unput (Context : in out Context_Type; c : Character) is
   begin
      yyUnput (Context, c, Context.dfa.yy_bp);
   end Unput;

%end
%if input
   function Input (Context : in out Context_Type) return Character is
      c : Character;
   begin
      Context.dfa.yy_ch_buf (Context.dfa.yy_c_buf_p) := Context.dfa.yy_hold_char;

      if Context.dfa.yy_ch_buf (Context.dfa.yy_c_buf_p) = YY_END_OF_BUFFER_CHAR then
         --  need more input
         Context.dfa.yytext_ptr := Context.dfa.yy_c_buf_p;
         Context.dfa.yy_c_buf_p := Context.dfa.yy_c_buf_p + 1;

         case yy_get_next_buffer (Context) is
            --  this code, unfortunately, is somewhat redundant with
            --  that above

         when EOB_ACT_END_OF_FILE =>
%if yywrap
            if yyWrap (Context) then
               Context.dfa.yy_c_buf_p := Context.dfa.yytext_ptr;
               return ASCII.NUL;
            end if;

            Context.dfa.yy_ch_buf (0) := ASCII.LF;
            Context.yy_n_chars := 1;
            Context.dfa.yy_ch_buf (Context.yy_n_chars) := YY_END_OF_BUFFER_CHAR;
            Context.dfa.yy_ch_buf (Context.yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;
            Context.yy_eof_has_been_seen := False;
            Context.yy_c_buf_p := 1;
            Context.dfa.yytext_ptr := Context.dfa.yy_c_buf_p;
            Context.dfa.yy_hold_char := Context.dfa.yy_ch_buf (Context.yy_c_buf_p);

            return Input;
%else
            Context.dfa.yy_c_buf_p := Context.dfa.yytext_ptr;
            return ASCII.NUL;
%end
         when EOB_ACT_RESTART_SCAN =>
            Context.dfa.yy_c_buf_p := Context.dfa.yytext_ptr;

         when EOB_ACT_LAST_MATCH =>
            raise UNEXPECTED_LAST_MATCH;
         end case;
      end if;

      c := Context.dfa.yy_ch_buf (Context.dfa.yy_c_buf_p);
      Context.dfa.yy_c_buf_p := Context.dfa.yy_c_buf_p + 1;
      Context.dfa.yy_hold_char := Context.dfa.yy_ch_buf (Context.dfa.yy_c_buf_p);

      return c;
   end Input;

%end
%if output
   procedure Output (Context : in out Context_Type; c : Character) is
   begin
      if Ada.Text_IO.Is_Open (Context.user_output_file) then
         Ada.Text_IO.Put (Context.user_output_file, c);
      else
         Ada.Text_IO.Put (c);
      end if;
   end Output;

   procedure Output_New_Line (Context : in out Context_Type) is
   begin
      if Ada.Text_IO.Is_Open (Context.user_output_file) then
         Ada.Text_IO.New_Line (Context.user_output_file);
      else
         Ada.Text_IO.New_Line;
      end if;
   end Output_New_Line;

   function Output_Column (Context : in Context_Type) return Ada.Text_IO.Count is
   begin
      if Ada.Text_IO.Is_Open (Context.user_output_file) then
         return Ada.Text_IO.Col (Context.user_output_file);
      else
         return Ada.Text_IO.Col;
      end if;
   end Output_Column;

%end
%if error
   function Input_Line (Context : in Context_Type) return Ada.Text_IO.Count is
   begin
      return Ada.Text_IO.Count (Context.Line_Number_Of_Saved_Tok_Line2);
   end Input_Line;

%end
%if yywrap
   --  default yywrap function - always treat EOF as an EOF
   function yyWrap (Context : in Context_Type) return Boolean is
   begin
%if yywrapcode
%yywrap
%else
      return True;
%end
   end yyWrap;

%end
   procedure Open_Input (Context : in out Context_Type; fname : in String) is
   begin
      Context.dfa.yy_init := True;
      Ada.Text_IO.Open (Context.user_input_file, Ada.Text_IO.In_File, fname);
%if yylineno
      Context.dfa.yylineno  := 1;
      Context.dfa.yylinecol := 0;
%end
   end Open_Input;

%if output
   procedure Create_Output (Context : in out Context_Type; fname : in String := "") is
   begin
      if fname /= "" then
         Ada.Text_IO.Create (Context.user_output_file, Ada.Text_IO.Out_File, fname);
      end if;
   end Create_Output;

%end
   procedure Close_Input (Context : in out Context_Type) is
   begin
      if Ada.Text_IO.Is_Open (Context.user_input_file) then
         Ada.Text_IO.Close (Context.user_input_file);
      end if;
   end Close_Input;

%if output
   procedure Close_Output (Context : in out Context_Type) is
   begin
      if Ada.Text_IO.Is_Open (Context.user_output_file) then
         Ada.Text_IO.Close (Context.user_output_file);
      end if;
   end Close_Output;

%end
%if error
   procedure Yy_Get_Token_Line (Context : in out Context_Type;
                                Yy_Line_String : out String;
                                Yy_Line_Length : out Natural ) is
   begin
      --  Currently processing line is either in saved token line1 or
      --  in saved token line2.
      if Context.Yy_Line_Number = Context.Line_Number_Of_Saved_Tok_Line1 then
         Context.Yy_Line_Length := Context.Saved_Tok_Line1.all'length;
         Context.Yy_Line_String ( Context.Yy_Line_String'First .. ( Context.Yy_Line_String'First + Context.Saved_Tok_Line1.all'length - 1 ))
           := Context.Saved_Tok_Line1 ( 1 .. Context.Saved_Tok_Line1.all'length );
      else
         Context.Yy_Line_Length := Context.Saved_Tok_Line2.all'length;
         Context.Yy_Line_String ( Context.Yy_Line_String'First .. ( Context.Yy_Line_String'First + Context.Saved_Tok_Line2.all'length - 1 ))
           := Context.Saved_Tok_Line2 ( 1 .. Context.Saved_Tok_Line2.all'length );
      end if;
   end Yy_Get_Token_Line;

   function Yy_Line_Number (Context : in Context_Type) return Natural is
   begin
      return Context.dfa.Tok_Begin_Line;
   end Yy_Line_Number;

   function Yy_Begin_Column (Context : in Context_Type) return Natural is
   begin
      return Context.dfa.Tok_Begin_Col;
   end Yy_Begin_Column;

   function Yy_End_Column (Context : in Context_Type) return Natural is
   begin
      return Context.dfa.Tok_End_Col;
   end Yy_End_Column;

%end
end ${NAME}_IO;
