1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2007, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
35 -- This is needed because the pragmas Warnings (Off) in Current_Session and
36 -- Default_Session (see below) do not work when compiling clients of this
37 -- package that instantiate generic units herein.
39 pragma Style_Checks
(All_Checks
);
40 -- Turn off alpha ordering check for subprograms, since we cannot
41 -- Put Finalize and Initialize in alpha order (see comments).
45 with Ada
.Strings
.Unbounded
;
46 with Ada
.Strings
.Fixed
;
47 with Ada
.Strings
.Maps
;
48 with Ada
.Unchecked_Deallocation
;
50 with GNAT
.Directory_Operations
;
51 with GNAT
.Dynamic_Tables
;
54 package body GNAT
.AWK
is
57 use Ada
.Strings
.Unbounded
;
65 type Mode
is abstract tagged null record;
66 -- This is the main type which is declared abstract. This type must be
67 -- derived for each split style.
69 type Mode_Access
is access Mode
'Class;
71 procedure Current_Line
(S
: Mode
; Session
: Session_Type
)
73 -- Split current line of Session using split mode S
75 ------------------------
76 -- Split on separator --
77 ------------------------
79 type Separator
(Size
: Positive) is new Mode
with record
80 Separators
: String (1 .. Size
);
83 procedure Current_Line
85 Session
: Session_Type
);
91 type Column
(Size
: Positive) is new Mode
with record
92 Columns
: Widths_Set
(1 .. Size
);
95 procedure Current_Line
(S
: Column
; Session
: Session_Type
);
99 procedure Free
is new Unchecked_Deallocation
100 (Split
.Mode
'Class, Split
.Mode_Access
);
106 type AWK_File
is access String;
108 package File_Table
is
109 new Dynamic_Tables
(AWK_File
, Natural, 1, 5, 50);
110 -- List of file names associated with a Session
112 procedure Free
is new Unchecked_Deallocation
(String, AWK_File
);
118 type Field_Slice
is record
122 -- This is a field slice (First .. Last) in session's current line
124 package Field_Table
is
125 new Dynamic_Tables
(Field_Slice
, Natural, 1, 10, 100);
126 -- List of fields for the current line
132 -- Define all patterns style: exact string, regular expression, boolean
137 type Pattern
is abstract tagged null record;
138 -- This is the main type which is declared abstract. This type must be
139 -- derived for each patterns style.
141 type Pattern_Access
is access Pattern
'Class;
145 Session
: Session_Type
) return Boolean
147 -- Returns True if P match for the current session and False otherwise
149 procedure Release
(P
: in out Pattern
);
150 -- Release memory used by the pattern structure
152 --------------------------
153 -- Exact string pattern --
154 --------------------------
156 type String_Pattern
is new Pattern
with record
157 Str
: Unbounded_String
;
163 Session
: Session_Type
) return Boolean;
165 --------------------------------
166 -- Regular expression pattern --
167 --------------------------------
169 type Pattern_Matcher_Access
is access Regpat
.Pattern_Matcher
;
171 type Regexp_Pattern
is new Pattern
with record
172 Regx
: Pattern_Matcher_Access
;
178 Session
: Session_Type
) return Boolean;
180 procedure Release
(P
: in out Regexp_Pattern
);
182 ------------------------------
183 -- Boolean function pattern --
184 ------------------------------
186 type Callback_Pattern
is new Pattern
with record
187 Pattern
: Pattern_Callback
;
191 (P
: Callback_Pattern
;
192 Session
: Session_Type
) return Boolean;
196 procedure Free
is new Unchecked_Deallocation
197 (Patterns
.Pattern
'Class, Patterns
.Pattern_Access
);
203 -- Define all action style : simple call, call with matches
207 type Action
is abstract tagged null record;
208 -- This is the main type which is declared abstract. This type must be
209 -- derived for each action style.
211 type Action_Access
is access Action
'Class;
215 Session
: Session_Type
) is abstract;
216 -- Call action A as required
222 type Simple_Action
is new Action
with record
223 Proc
: Action_Callback
;
228 Session
: Session_Type
);
230 -------------------------
231 -- Action with matches --
232 -------------------------
234 type Match_Action
is new Action
with record
235 Proc
: Match_Action_Callback
;
240 Session
: Session_Type
);
244 procedure Free
is new Unchecked_Deallocation
245 (Actions
.Action
'Class, Actions
.Action_Access
);
247 --------------------------
248 -- Pattern/Action table --
249 --------------------------
251 type Pattern_Action
is record
252 Pattern
: Patterns
.Pattern_Access
; -- If Pattern is True
253 Action
: Actions
.Action_Access
; -- Action will be called
256 package Pattern_Action_Table
is
257 new Dynamic_Tables
(Pattern_Action
, Natural, 1, 5, 50);
263 type Session_Data
is record
264 Current_File
: Text_IO
.File_Type
;
265 Current_Line
: Unbounded_String
;
266 Separators
: Split
.Mode_Access
;
267 Files
: File_Table
.Instance
;
268 File_Index
: Natural := 0;
269 Fields
: Field_Table
.Instance
;
270 Filters
: Pattern_Action_Table
.Instance
;
273 Matches
: Regpat
.Match_Array
(0 .. 100);
274 -- Latest matches for the regexp pattern
278 new Unchecked_Deallocation
(Session_Data
, Session_Data_Access
);
284 procedure Initialize
(Session
: in out Session_Type
) is
286 Session
.Data
:= new Session_Data
;
288 -- Initialize separators
290 Session
.Data
.Separators
:=
291 new Split
.Separator
'(Default_Separators'Length, Default_Separators);
293 -- Initialize all tables
295 File_Table.Init (Session.Data.Files);
296 Field_Table.Init (Session.Data.Fields);
297 Pattern_Action_Table.Init (Session.Data.Filters);
300 -----------------------
301 -- Session Variables --
302 -----------------------
304 -- These must come after the body of Initialize, since they make
305 -- implicit calls to Initialize at elaboration time.
307 Def_Session : Session_Type;
308 Cur_Session : Session_Type;
314 -- Note: Finalize must come after Initialize and the definition
315 -- of the Def_Session and Cur_Session variables, since it references
318 procedure Finalize (Session : in out Session_Type) is
320 -- We release the session data only if it is not the default session
322 if Session.Data /= Def_Session.Data then
325 -- Since we have closed the current session, set it to point now to
326 -- the default session.
328 Cur_Session.Data := Def_Session.Data;
332 ----------------------
333 -- Private Services --
334 ----------------------
336 function Always_True return Boolean;
337 -- A function that always returns True
339 function Apply_Filters
340 (Session : Session_Type) return Boolean;
341 -- Apply any filters for which the Pattern is True for Session. It returns
342 -- True if a least one filters has been applied (i.e. associated action
343 -- callback has been called).
345 procedure Open_Next_File
346 (Session : Session_Type);
347 pragma Inline (Open_Next_File);
348 -- Open next file for Session closing current file if needed. It raises
349 -- End_Error if there is no more file in the table.
351 procedure Raise_With_Info
352 (E : Exceptions.Exception_Id;
354 Session : Session_Type);
355 pragma No_Return (Raise_With_Info);
356 -- Raises exception E with the message prepended with the current line
357 -- number and the filename if possible.
359 procedure Read_Line (Session : Session_Type);
360 -- Read a line for the Session and set Current_Line
362 procedure Split_Line (Session : Session_Type);
363 -- Split session's Current_Line according to the session separators and
364 -- set the Fields table. This procedure can be called at any time.
366 ----------------------
367 -- Private Packages --
368 ----------------------
374 package body Actions is
382 Session : Session_Type)
384 pragma Unreferenced (Session);
395 Session : Session_Type)
398 A.Proc (Session.Data.Matches);
407 package body Patterns is
415 Session : Session_Type) return Boolean
418 return P.Str = Field (P.Rank, Session);
427 Session : Session_Type) return Boolean
429 use type Regpat.Match_Location;
432 (P.Regx.all, Field (P.Rank, Session), Session.Data.Matches);
433 return Session.Data.Matches (0) /= Regpat.No_Match;
441 (P : Callback_Pattern;
442 Session : Session_Type) return Boolean
444 pragma Unreferenced (Session);
446 return P.Pattern.all;
453 procedure Release (P : in out Pattern) is
454 pragma Unreferenced (P);
463 procedure Release (P : in out Regexp_Pattern) is
464 procedure Free is new Unchecked_Deallocation
465 (Regpat.Pattern_Matcher, Pattern_Matcher_Access);
476 package body Split is
484 procedure Current_Line (S : Separator; Session : Session_Type) is
485 Line : constant String := To_String (Session.Data.Current_Line);
486 Fields : Field_Table.Instance renames Session.Data.Fields;
491 Seps : constant Maps.Character_Set := Maps.To_Set (S.Separators);
494 -- First field start here
498 -- Record the first field start position which is the first character
501 Field_Table.Increment_Last (Fields);
502 Fields.Table (Field_Table.Last (Fields)).First := Start;
505 -- Look for next separator
508 (Source => Line (Start .. Line'Last),
513 Fields.Table (Field_Table.Last (Fields)).Last := Stop - 1;
515 -- If separators are set to the default (space and tab) we skip
516 -- all spaces and tabs following current field.
518 if S.Separators = Default_Separators then
520 (Line (Stop + 1 .. Line'Last),
521 Maps.To_Set (Default_Separators),
532 -- Record in the field table the start of this new field
534 Field_Table.Increment_Last (Fields);
535 Fields.Table (Field_Table.Last (Fields)).First := Start;
539 Fields.Table (Field_Table.Last (Fields)).Last := Line'Last;
546 procedure Current_Line (S : Column; Session : Session_Type) is
547 Line : constant String := To_String (Session.Data.Current_Line);
548 Fields : Field_Table.Instance renames Session.Data.Fields;
549 Start : Positive := Line'First;
552 -- Record the first field start position which is the first character
555 for C in 1 .. S.Columns'Length loop
557 Field_Table.Increment_Last (Fields);
559 Fields.Table (Field_Table.Last (Fields)).First := Start;
561 Start := Start + S.Columns (C);
563 Fields.Table (Field_Table.Last (Fields)).Last := Start - 1;
567 -- If there is some remaining character on the line, add them in a
570 if Start - 1 < Line'Length then
572 Field_Table.Increment_Last (Fields);
574 Fields.Table (Field_Table.Last (Fields)).First := Start;
576 Fields.Table (Field_Table.Last (Fields)).Last := Line'Last;
588 Session : Session_Type)
590 Files : File_Table.Instance renames Session.Data.Files;
593 if OS_Lib.Is_Regular_File (Filename) then
594 File_Table.Increment_Last (Files);
595 Files.Table (File_Table.Last (Files)) := new String'(Filename
);
598 (File_Error
'Identity,
599 "File " & Filename
& " not found.",
609 Add_File
(Filename
, Cur_Session
);
619 Number_Of_Files_Added
: out Natural;
620 Session
: Session_Type
)
622 use Directory_Operations
;
625 Filename
: String (1 .. 200);
629 Number_Of_Files_Added
:= 0;
631 Open
(Dir
, Directory
);
634 Read
(Dir
, Filename
, Last
);
637 Add_File
(Filename
(1 .. Last
), Session
);
638 Number_Of_Files_Added
:= Number_Of_Files_Added
+ 1;
646 (File_Error
'Identity,
647 "Error scaning directory " & Directory
648 & " for files " & Filenames
& '.',
655 Number_Of_Files_Added
: out Natural)
659 Add_Files
(Directory
, Filenames
, Number_Of_Files_Added
, Cur_Session
);
666 function Always_True
return Boolean is
675 function Apply_Filters
676 (Session
: Session_Type
) return Boolean
678 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
679 Results
: Boolean := False;
682 -- Iterate through the filters table, if pattern match call action
684 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
685 if Patterns
.Match
(Filters
.Table
(F
).Pattern
.all, Session
) then
687 Actions
.Call
(Filters
.Table
(F
).Action
.all, Session
);
698 procedure Close
(Session
: Session_Type
) is
699 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
700 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
703 -- Close current file if needed
705 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
706 Text_IO
.Close
(Session
.Data
.Current_File
);
709 -- Release separators
711 Free
(Session
.Data
.Separators
);
713 -- Release Filters table
715 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
716 Patterns
.Release
(Filters
.Table
(F
).Pattern
.all);
717 Free
(Filters
.Table
(F
).Pattern
);
718 Free
(Filters
.Table
(F
).Action
);
721 for F
in 1 .. File_Table
.Last
(Files
) loop
722 Free
(Files
.Table
(F
));
725 File_Table
.Set_Last
(Session
.Data
.Files
, 0);
726 Field_Table
.Set_Last
(Session
.Data
.Fields
, 0);
727 Pattern_Action_Table
.Set_Last
(Session
.Data
.Filters
, 0);
729 Session
.Data
.NR
:= 0;
730 Session
.Data
.FNR
:= 0;
731 Session
.Data
.File_Index
:= 0;
732 Session
.Data
.Current_Line
:= Null_Unbounded_String
;
735 ---------------------
736 -- Current_Session --
737 ---------------------
739 function Current_Session
return Session_Type
is
741 pragma Warnings
(Off
);
743 -- ???The above return statement violates the Ada 2005 rule forbidding
744 -- copying of limited objects (see RM-7.5(2.8/2)). When compiled with
745 -- -gnatg, the compiler gives a warning instead of an error, so we can
747 pragma Warnings
(On
);
750 ---------------------
751 -- Default_Session --
752 ---------------------
754 function Default_Session
return Session_Type
is
756 pragma Warnings
(Off
);
758 -- ???The above return statement violates the Ada 2005 rule forbidding
759 -- copying of limited objects (see RM-7.5(2.8/2)). When compiled with
760 -- -gnatg, the compiler gives a warning instead of an error, so we can
762 pragma Warnings
(On
);
769 function Discrete_Field
771 Session
: Session_Type
) return Discrete
774 return Discrete
'Value (Field
(Rank
, Session
));
777 function Discrete_Field_Current_Session
778 (Rank
: Count
) return Discrete
is
779 function Do_It
is new Discrete_Field
(Discrete
);
781 return Do_It
(Rank
, Cur_Session
);
782 end Discrete_Field_Current_Session
;
789 (Session
: Session_Type
) return Boolean
792 return Session
.Data
.File_Index
= File_Table
.Last
(Session
.Data
.Files
)
793 and then End_Of_File
(Session
);
800 return End_Of_Data
(Cur_Session
);
808 (Session
: Session_Type
) return Boolean
811 return Text_IO
.End_Of_File
(Session
.Data
.Current_File
);
818 return End_Of_File
(Cur_Session
);
827 Session
: Session_Type
) return String
829 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
832 if Rank
> Number_Of_Fields
(Session
) then
834 (Field_Error
'Identity,
835 "Field number" & Count
'Image (Rank
) & " does not exist.",
840 -- Returns the whole line, this is what $0 does under Session_Type
842 return To_String
(Session
.Data
.Current_Line
);
845 return Slice
(Session
.Data
.Current_Line
,
846 Fields
.Table
(Positive (Rank
)).First
,
847 Fields
.Table
(Positive (Rank
)).Last
);
852 (Rank
: Count
) return String
855 return Field
(Rank
, Cur_Session
);
860 Session
: Session_Type
) return Integer
863 return Integer'Value (Field
(Rank
, Session
));
866 when Constraint_Error
=>
868 (Field_Error
'Identity,
869 "Field number" & Count
'Image (Rank
)
870 & " cannot be converted to an integer.",
875 (Rank
: Count
) return Integer
878 return Field
(Rank
, Cur_Session
);
883 Session
: Session_Type
) return Float
886 return Float'Value (Field
(Rank
, Session
));
889 when Constraint_Error
=>
891 (Field_Error
'Identity,
892 "Field number" & Count
'Image (Rank
)
893 & " cannot be converted to a float.",
898 (Rank
: Count
) return Float
901 return Field
(Rank
, Cur_Session
);
909 (Session
: Session_Type
) return String
911 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
914 if Session
.Data
.File_Index
= 0 then
917 return Files
.Table
(Session
.Data
.File_Index
).all;
925 return File
(Cur_Session
);
932 procedure For_Every_Line
933 (Separators
: String := Use_Current
;
934 Filename
: String := Use_Current
;
935 Callbacks
: Callback_Mode
:= None
;
936 Session
: Session_Type
)
941 Open
(Separators
, Filename
, Session
);
943 while not End_Of_Data
(Session
) loop
945 Split_Line
(Session
);
947 if Callbacks
in Only
.. Pass_Through
then
950 pragma Unreferenced
(Discard
);
952 Discard
:= Apply_Filters
(Session
);
956 if Callbacks
/= Only
then
966 procedure For_Every_Line_Current_Session
967 (Separators
: String := Use_Current
;
968 Filename
: String := Use_Current
;
969 Callbacks
: Callback_Mode
:= None
)
971 procedure Do_It
is new For_Every_Line
(Action
);
973 Do_It
(Separators
, Filename
, Callbacks
, Cur_Session
);
974 end For_Every_Line_Current_Session
;
981 (Callbacks
: Callback_Mode
:= None
;
982 Session
: Session_Type
)
984 Filter_Active
: Boolean;
987 if not Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
993 Split_Line
(Session
);
1001 Filter_Active
:= Apply_Filters
(Session
);
1002 exit when not Filter_Active
;
1004 when Pass_Through
=>
1005 Filter_Active
:= Apply_Filters
(Session
);
1013 (Callbacks
: Callback_Mode
:= None
)
1016 Get_Line
(Callbacks
, Cur_Session
);
1019 ----------------------
1020 -- Number_Of_Fields --
1021 ----------------------
1023 function Number_Of_Fields
1024 (Session
: Session_Type
) return Count
1027 return Count
(Field_Table
.Last
(Session
.Data
.Fields
));
1028 end Number_Of_Fields
;
1030 function Number_Of_Fields
1034 return Number_Of_Fields
(Cur_Session
);
1035 end Number_Of_Fields
;
1037 --------------------------
1038 -- Number_Of_File_Lines --
1039 --------------------------
1041 function Number_Of_File_Lines
1042 (Session
: Session_Type
) return Count
1045 return Count
(Session
.Data
.FNR
);
1046 end Number_Of_File_Lines
;
1048 function Number_Of_File_Lines
1052 return Number_Of_File_Lines
(Cur_Session
);
1053 end Number_Of_File_Lines
;
1055 ---------------------
1056 -- Number_Of_Files --
1057 ---------------------
1059 function Number_Of_Files
1060 (Session
: Session_Type
) return Natural
1062 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
1064 return File_Table
.Last
(Files
);
1065 end Number_Of_Files
;
1067 function Number_Of_Files
1071 return Number_Of_Files
(Cur_Session
);
1072 end Number_Of_Files
;
1074 ---------------------
1075 -- Number_Of_Lines --
1076 ---------------------
1078 function Number_Of_Lines
1079 (Session
: Session_Type
) return Count
1082 return Count
(Session
.Data
.NR
);
1083 end Number_Of_Lines
;
1085 function Number_Of_Lines
1089 return Number_Of_Lines
(Cur_Session
);
1090 end Number_Of_Lines
;
1097 (Separators
: String := Use_Current
;
1098 Filename
: String := Use_Current
;
1099 Session
: Session_Type
)
1102 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
1103 raise Session_Error
;
1106 if Filename
/= Use_Current
then
1107 File_Table
.Init
(Session
.Data
.Files
);
1108 Add_File
(Filename
, Session
);
1111 if Separators
/= Use_Current
then
1112 Set_Field_Separators
(Separators
, Session
);
1115 Open_Next_File
(Session
);
1123 (Separators
: String := Use_Current
;
1124 Filename
: String := Use_Current
)
1127 Open
(Separators
, Filename
, Cur_Session
);
1130 --------------------
1131 -- Open_Next_File --
1132 --------------------
1134 procedure Open_Next_File
1135 (Session
: Session_Type
)
1137 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
1140 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
1141 Text_IO
.Close
(Session
.Data
.Current_File
);
1144 Session
.Data
.File_Index
:= Session
.Data
.File_Index
+ 1;
1146 -- If there are no mores file in the table, raise End_Error
1148 if Session
.Data
.File_Index
> File_Table
.Last
(Files
) then
1153 (File
=> Session
.Data
.Current_File
,
1154 Name
=> Files
.Table
(Session
.Data
.File_Index
).all,
1155 Mode
=> Text_IO
.In_File
);
1163 (Separators
: String := Use_Current
;
1164 Filename
: String := Use_Current
;
1165 Session
: Session_Type
)
1167 Filter_Active
: Boolean;
1168 pragma Unreferenced
(Filter_Active
);
1171 Open
(Separators
, Filename
, Session
);
1173 while not End_Of_Data
(Session
) loop
1174 Get_Line
(None
, Session
);
1175 Filter_Active
:= Apply_Filters
(Session
);
1182 (Separators
: String := Use_Current
;
1183 Filename
: String := Use_Current
)
1186 Parse
(Separators
, Filename
, Cur_Session
);
1189 ---------------------
1190 -- Raise_With_Info --
1191 ---------------------
1193 procedure Raise_With_Info
1194 (E
: Exceptions
.Exception_Id
;
1196 Session
: Session_Type
)
1198 function Filename
return String;
1199 -- Returns current filename and "??" if this information is not
1202 function Line
return String;
1203 -- Returns current line number without the leading space
1209 function Filename
return String is
1210 File
: constant String := AWK
.File
(Session
);
1223 function Line
return String is
1224 L
: constant String := Natural'Image (Session
.Data
.FNR
);
1226 return L
(2 .. L
'Last);
1229 -- Start of processing for Raise_With_Info
1232 Exceptions
.Raise_Exception
1234 '[' & Filename
& ':' & Line
& "] " & Message
);
1235 raise Constraint_Error
; -- to please GNAT as this is a No_Return proc
1236 end Raise_With_Info
;
1242 procedure Read_Line
(Session
: Session_Type
) is
1244 function Read_Line
return String;
1245 -- Read a line in the current file. This implementation is recursive
1246 -- and does not have a limitation on the line length.
1248 NR
: Natural renames Session
.Data
.NR
;
1249 FNR
: Natural renames Session
.Data
.FNR
;
1255 function Read_Line
return String is
1256 Buffer
: String (1 .. 1_024
);
1260 Text_IO
.Get_Line
(Session
.Data
.Current_File
, Buffer
, Last
);
1262 if Last
= Buffer
'Last then
1263 return Buffer
& Read_Line
;
1265 return Buffer
(1 .. Last
);
1269 -- Start of processing for Read_Line
1272 if End_Of_File
(Session
) then
1273 Open_Next_File
(Session
);
1277 Session
.Data
.Current_Line
:= To_Unbounded_String
(Read_Line
);
1290 Action
: Action_Callback
;
1291 Session
: Session_Type
)
1293 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1294 U_Pattern
: constant Unbounded_String
:= To_Unbounded_String
(Pattern
);
1297 Pattern_Action_Table
.Increment_Last
(Filters
);
1299 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1300 (Pattern
=> new Patterns
.String_Pattern
'(U_Pattern, Field),
1301 Action => new Actions.Simple_Action'(Proc
=> Action
));
1307 Action
: Action_Callback
)
1310 Register
(Field
, Pattern
, Action
, Cur_Session
);
1315 Pattern
: GNAT
.Regpat
.Pattern_Matcher
;
1316 Action
: Action_Callback
;
1317 Session
: Session_Type
)
1319 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1321 A_Pattern
: constant Patterns
.Pattern_Matcher_Access
:=
1322 new Regpat
.Pattern_Matcher
'(Pattern);
1324 Pattern_Action_Table.Increment_Last (Filters);
1326 Filters.Table (Pattern_Action_Table.Last (Filters)) :=
1327 (Pattern => new Patterns.Regexp_Pattern'(A_Pattern
, Field
),
1328 Action
=> new Actions
.Simple_Action
'(Proc => Action));
1333 Pattern : GNAT.Regpat.Pattern_Matcher;
1334 Action : Action_Callback)
1337 Register (Field, Pattern, Action, Cur_Session);
1342 Pattern : GNAT.Regpat.Pattern_Matcher;
1343 Action : Match_Action_Callback;
1344 Session : Session_Type)
1346 Filters : Pattern_Action_Table.Instance renames Session.Data.Filters;
1348 A_Pattern : constant Patterns.Pattern_Matcher_Access :=
1349 new Regpat.Pattern_Matcher'(Pattern
);
1351 Pattern_Action_Table
.Increment_Last
(Filters
);
1353 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1354 (Pattern
=> new Patterns
.Regexp_Pattern
'(A_Pattern, Field),
1355 Action => new Actions.Match_Action'(Proc
=> Action
));
1360 Pattern
: GNAT
.Regpat
.Pattern_Matcher
;
1361 Action
: Match_Action_Callback
)
1364 Register
(Field
, Pattern
, Action
, Cur_Session
);
1368 (Pattern
: Pattern_Callback
;
1369 Action
: Action_Callback
;
1370 Session
: Session_Type
)
1372 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1375 Pattern_Action_Table
.Increment_Last
(Filters
);
1377 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1378 (Pattern
=> new Patterns
.Callback_Pattern
'(Pattern => Pattern),
1379 Action => new Actions.Simple_Action'(Proc
=> Action
));
1383 (Pattern
: Pattern_Callback
;
1384 Action
: Action_Callback
)
1387 Register
(Pattern
, Action
, Cur_Session
);
1391 (Action
: Action_Callback
;
1392 Session
: Session_Type
)
1395 Register
(Always_True
'Access, Action
, Session
);
1399 (Action
: Action_Callback
)
1402 Register
(Action
, Cur_Session
);
1409 procedure Set_Current
(Session
: Session_Type
) is
1411 Cur_Session
.Data
:= Session
.Data
;
1414 --------------------------
1415 -- Set_Field_Separators --
1416 --------------------------
1418 procedure Set_Field_Separators
1419 (Separators
: String := Default_Separators
;
1420 Session
: Session_Type
)
1423 Free
(Session
.Data
.Separators
);
1425 Session
.Data
.Separators
:=
1426 new Split
.Separator
'(Separators'Length, Separators);
1428 -- If there is a current line read, split it according to the new
1431 if Session.Data.Current_Line /= Null_Unbounded_String then
1432 Split_Line (Session);
1434 end Set_Field_Separators;
1436 procedure Set_Field_Separators
1437 (Separators : String := Default_Separators)
1440 Set_Field_Separators (Separators, Cur_Session);
1441 end Set_Field_Separators;
1443 ----------------------
1444 -- Set_Field_Widths --
1445 ----------------------
1447 procedure Set_Field_Widths
1448 (Field_Widths : Widths_Set;
1449 Session : Session_Type)
1452 Free (Session.Data.Separators);
1454 Session.Data.Separators :=
1455 new Split.Column'(Field_Widths
'Length, Field_Widths
);
1457 -- If there is a current line read, split it according to
1458 -- the new separators.
1460 if Session
.Data
.Current_Line
/= Null_Unbounded_String
then
1461 Split_Line
(Session
);
1463 end Set_Field_Widths
;
1465 procedure Set_Field_Widths
1466 (Field_Widths
: Widths_Set
)
1469 Set_Field_Widths
(Field_Widths
, Cur_Session
);
1470 end Set_Field_Widths
;
1476 procedure Split_Line
(Session
: Session_Type
) is
1477 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
1479 Field_Table
.Init
(Fields
);
1480 Split
.Current_Line
(Session
.Data
.Separators
.all, Session
);
1484 -- We have declared two sessions but both should share the same data.
1485 -- The current session must point to the default session as its initial
1486 -- value. So first we release the session data then we set current
1487 -- session data to point to default session data.
1489 Free
(Cur_Session
.Data
);
1490 Cur_Session
.Data
:= Def_Session
.Data
;