1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2017, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
34 with Ada
.Strings
.Unbounded
;
35 with Ada
.Strings
.Fixed
;
36 with Ada
.Strings
.Maps
;
37 with Ada
.Unchecked_Deallocation
;
39 with GNAT
.Directory_Operations
;
40 with GNAT
.Dynamic_Tables
;
43 package body GNAT
.AWK
is
46 use Ada
.Strings
.Unbounded
;
48 -----------------------
49 -- Local subprograms --
50 -----------------------
52 -- The following two subprograms provide a functional interface to the
53 -- two special session variables, that are manipulated explicitly by
54 -- Finalize, but must be declared after Finalize to prevent static
55 -- elaboration warnings.
57 function Get_Def
return Session_Data_Access
;
66 type Mode
is abstract tagged null record;
67 -- This is the main type which is declared abstract. This type must be
68 -- derived for each split style.
70 type Mode_Access
is access Mode
'Class;
72 procedure Current_Line
(S
: Mode
; Session
: Session_Type
)
74 -- Split current line of Session using split mode S
76 ------------------------
77 -- Split on separator --
78 ------------------------
80 type Separator
(Size
: Positive) is new Mode
with record
81 Separators
: String (1 .. Size
);
84 procedure Current_Line
86 Session
: Session_Type
);
92 type Column
(Size
: Positive) is new Mode
with record
93 Columns
: Widths_Set
(1 .. Size
);
96 procedure Current_Line
(S
: Column
; Session
: Session_Type
);
100 procedure Free
is new Unchecked_Deallocation
101 (Split
.Mode
'Class, Split
.Mode_Access
);
107 type AWK_File
is access String;
109 package File_Table
is
110 new Dynamic_Tables
(AWK_File
, Natural, 1, 5, 50);
111 -- List of file names associated with a Session
113 procedure Free
is new Unchecked_Deallocation
(String, AWK_File
);
119 type Field_Slice
is record
123 -- This is a field slice (First .. Last) in session's current line
125 package Field_Table
is
126 new Dynamic_Tables
(Field_Slice
, Natural, 1, 10, 100);
127 -- List of fields for the current line
133 -- Define all patterns style: exact string, regular expression, boolean
138 type Pattern
is abstract tagged null record;
139 -- This is the main type which is declared abstract. This type must be
140 -- derived for each patterns style.
142 type Pattern_Access
is access Pattern
'Class;
146 Session
: Session_Type
) return Boolean
148 -- Returns True if P match for the current session and False otherwise
150 procedure Release
(P
: in out Pattern
);
151 -- Release memory used by the pattern structure
153 --------------------------
154 -- Exact string pattern --
155 --------------------------
157 type String_Pattern
is new Pattern
with record
158 Str
: Unbounded_String
;
164 Session
: Session_Type
) return Boolean;
166 --------------------------------
167 -- Regular expression pattern --
168 --------------------------------
170 type Pattern_Matcher_Access
is access Regpat
.Pattern_Matcher
;
172 type Regexp_Pattern
is new Pattern
with record
173 Regx
: Pattern_Matcher_Access
;
179 Session
: Session_Type
) return Boolean;
181 procedure Release
(P
: in out Regexp_Pattern
);
183 ------------------------------
184 -- Boolean function pattern --
185 ------------------------------
187 type Callback_Pattern
is new Pattern
with record
188 Pattern
: Pattern_Callback
;
192 (P
: Callback_Pattern
;
193 Session
: Session_Type
) return Boolean;
197 procedure Free
is new Unchecked_Deallocation
198 (Patterns
.Pattern
'Class, Patterns
.Pattern_Access
);
204 -- Define all action style : simple call, call with matches
208 type Action
is abstract tagged null record;
209 -- This is the main type which is declared abstract. This type must be
210 -- derived for each action style.
212 type Action_Access
is access Action
'Class;
216 Session
: Session_Type
) is abstract;
217 -- Call action A as required
223 type Simple_Action
is new Action
with record
224 Proc
: Action_Callback
;
229 Session
: Session_Type
);
231 -------------------------
232 -- Action with matches --
233 -------------------------
235 type Match_Action
is new Action
with record
236 Proc
: Match_Action_Callback
;
241 Session
: Session_Type
);
245 procedure Free
is new Unchecked_Deallocation
246 (Actions
.Action
'Class, Actions
.Action_Access
);
248 --------------------------
249 -- Pattern/Action table --
250 --------------------------
252 type Pattern_Action
is record
253 Pattern
: Patterns
.Pattern_Access
; -- If Pattern is True
254 Action
: Actions
.Action_Access
; -- Action will be called
257 package Pattern_Action_Table
is
258 new Dynamic_Tables
(Pattern_Action
, Natural, 1, 5, 50);
264 type Session_Data
is record
265 Current_File
: Text_IO
.File_Type
;
266 Current_Line
: Unbounded_String
;
267 Separators
: Split
.Mode_Access
;
268 Files
: File_Table
.Instance
;
269 File_Index
: Natural := 0;
270 Fields
: Field_Table
.Instance
;
271 Filters
: Pattern_Action_Table
.Instance
;
274 Matches
: Regpat
.Match_Array
(0 .. 100);
275 -- Latest matches for the regexp pattern
279 new Unchecked_Deallocation
(Session_Data
, Session_Data_Access
);
285 procedure Finalize
(Session
: in out Session_Type
) is
287 -- We release the session data only if it is not the default session
289 if Session
.Data
/= Get_Def
then
290 -- Release separators
292 Free
(Session
.Data
.Separators
);
296 -- Since we have closed the current session, set it to point now to
297 -- the default session.
307 procedure Initialize
(Session
: in out Session_Type
) is
309 Session
.Data
:= new Session_Data
;
311 -- Initialize separators
313 Session
.Data
.Separators
:=
314 new Split
.Separator
'(Default_Separators'Length, Default_Separators);
316 -- Initialize all tables
318 File_Table.Init (Session.Data.Files);
319 Field_Table.Init (Session.Data.Fields);
320 Pattern_Action_Table.Init (Session.Data.Filters);
323 -----------------------
324 -- Session Variables --
325 -----------------------
327 Def_Session : Session_Type;
328 Cur_Session : Session_Type;
330 ----------------------
331 -- Private Services --
332 ----------------------
334 function Always_True return Boolean;
335 -- A function that always returns True
337 function Apply_Filters
338 (Session : Session_Type) return Boolean;
339 -- Apply any filters for which the Pattern is True for Session. It returns
340 -- True if a least one filters has been applied (i.e. associated action
341 -- callback has been called).
343 procedure Open_Next_File
344 (Session : Session_Type);
345 pragma Inline (Open_Next_File);
346 -- Open next file for Session closing current file if needed. It raises
347 -- End_Error if there is no more file in the table.
349 procedure Raise_With_Info
350 (E : Exceptions.Exception_Id;
352 Session : Session_Type);
353 pragma No_Return (Raise_With_Info);
354 -- Raises exception E with the message prepended with the current line
355 -- number and the filename if possible.
357 procedure Read_Line (Session : Session_Type);
358 -- Read a line for the Session and set Current_Line
360 procedure Split_Line (Session : Session_Type);
361 -- Split session's Current_Line according to the session separators and
362 -- set the Fields table. This procedure can be called at any time.
364 ----------------------
365 -- Private Packages --
366 ----------------------
372 package body Actions is
380 Session : Session_Type)
382 pragma Unreferenced (Session);
393 Session : Session_Type)
396 A.Proc (Session.Data.Matches);
405 package body Patterns is
413 Session : Session_Type) return Boolean
416 return P.Str = Field (P.Rank, Session);
425 Session : Session_Type) return Boolean
427 use type Regpat.Match_Location;
430 (P.Regx.all, Field (P.Rank, Session), Session.Data.Matches);
431 return Session.Data.Matches (0) /= Regpat.No_Match;
439 (P : Callback_Pattern;
440 Session : Session_Type) return Boolean
442 pragma Unreferenced (Session);
444 return P.Pattern.all;
451 procedure Release (P : in out Pattern) is
452 pragma Unreferenced (P);
461 procedure Release (P : in out Regexp_Pattern) is
462 procedure Free is new Unchecked_Deallocation
463 (Regpat.Pattern_Matcher, Pattern_Matcher_Access);
474 package body Split is
482 procedure Current_Line (S : Separator; Session : Session_Type) is
483 Line : constant String := To_String (Session.Data.Current_Line);
484 Fields : Field_Table.Instance renames Session.Data.Fields;
485 Seps : constant Maps.Character_Set := Maps.To_Set (S.Separators);
491 -- First field start here
495 -- Record the first field start position which is the first character
498 Field_Table.Increment_Last (Fields);
499 Fields.Table (Field_Table.Last (Fields)).First := Start;
502 -- Look for next separator
505 (Source => Line (Start .. Line'Last),
510 Fields.Table (Field_Table.Last (Fields)).Last := Stop - 1;
512 -- If separators are set to the default (space and tab) we skip
513 -- all spaces and tabs following current field.
515 if S.Separators = Default_Separators then
517 (Line (Stop + 1 .. Line'Last),
518 Maps.To_Set (Default_Separators),
530 -- Record in the field table the start of this new field
532 Field_Table.Increment_Last (Fields);
533 Fields.Table (Field_Table.Last (Fields)).First := Start;
537 Fields.Table (Field_Table.Last (Fields)).Last := Line'Last;
544 procedure Current_Line (S : Column; Session : Session_Type) is
545 Line : constant String := To_String (Session.Data.Current_Line);
546 Fields : Field_Table.Instance renames Session.Data.Fields;
547 Start : Positive := Line'First;
550 -- Record the first field start position which is the first character
553 for C in 1 .. S.Columns'Length loop
555 Field_Table.Increment_Last (Fields);
557 Fields.Table (Field_Table.Last (Fields)).First := Start;
559 Start := Start + S.Columns (C);
561 Fields.Table (Field_Table.Last (Fields)).Last := Start - 1;
565 -- If there is some remaining character on the line, add them in a
568 if Start - 1 < Line'Length then
570 Field_Table.Increment_Last (Fields);
572 Fields.Table (Field_Table.Last (Fields)).First := Start;
574 Fields.Table (Field_Table.Last (Fields)).Last := Line'Last;
586 Session : Session_Type)
588 Files : File_Table.Instance renames Session.Data.Files;
591 if OS_Lib.Is_Regular_File (Filename) then
592 File_Table.Increment_Last (Files);
593 Files.Table (File_Table.Last (Files)) := new String'(Filename
);
596 (File_Error
'Identity,
597 "File " & Filename
& " not found.",
607 Add_File
(Filename
, Cur_Session
);
617 Number_Of_Files_Added
: out Natural;
618 Session
: Session_Type
)
620 use Directory_Operations
;
623 Filename
: String (1 .. 200);
627 Number_Of_Files_Added
:= 0;
629 Open
(Dir
, Directory
);
632 Read
(Dir
, Filename
, Last
);
635 Add_File
(Filename
(1 .. Last
), Session
);
636 Number_Of_Files_Added
:= Number_Of_Files_Added
+ 1;
644 (File_Error
'Identity,
645 "Error scanning directory " & Directory
646 & " for files " & Filenames
& '.',
653 Number_Of_Files_Added
: out Natural)
657 Add_Files
(Directory
, Filenames
, Number_Of_Files_Added
, Cur_Session
);
664 function Always_True
return Boolean is
673 function Apply_Filters
674 (Session
: Session_Type
) return Boolean
676 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
677 Results
: Boolean := False;
680 -- Iterate through the filters table, if pattern match call action
682 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
683 if Patterns
.Match
(Filters
.Table
(F
).Pattern
.all, Session
) then
685 Actions
.Call
(Filters
.Table
(F
).Action
.all, Session
);
696 procedure Close
(Session
: Session_Type
) is
697 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
698 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
701 -- Close current file if needed
703 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
704 Text_IO
.Close
(Session
.Data
.Current_File
);
707 -- Release Filters table
709 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
710 Patterns
.Release
(Filters
.Table
(F
).Pattern
.all);
711 Free
(Filters
.Table
(F
).Pattern
);
712 Free
(Filters
.Table
(F
).Action
);
715 for F
in 1 .. File_Table
.Last
(Files
) loop
716 Free
(Files
.Table
(F
));
719 File_Table
.Set_Last
(Session
.Data
.Files
, 0);
720 Field_Table
.Set_Last
(Session
.Data
.Fields
, 0);
721 Pattern_Action_Table
.Set_Last
(Session
.Data
.Filters
, 0);
723 Session
.Data
.NR
:= 0;
724 Session
.Data
.FNR
:= 0;
725 Session
.Data
.File_Index
:= 0;
726 Session
.Data
.Current_Line
:= Null_Unbounded_String
;
729 ---------------------
730 -- Current_Session --
731 ---------------------
733 function Current_Session
return not null access Session_Type
is
735 return Cur_Session
.Self
;
738 ---------------------
739 -- Default_Session --
740 ---------------------
742 function Default_Session
return not null access Session_Type
is
744 return Def_Session
.Self
;
751 function Discrete_Field
753 Session
: Session_Type
) return Discrete
756 return Discrete
'Value (Field
(Rank
, Session
));
759 function Discrete_Field_Current_Session
760 (Rank
: Count
) return Discrete
is
761 function Do_It
is new Discrete_Field
(Discrete
);
763 return Do_It
(Rank
, Cur_Session
);
764 end Discrete_Field_Current_Session
;
771 (Session
: Session_Type
) return Boolean
774 return Session
.Data
.File_Index
= File_Table
.Last
(Session
.Data
.Files
)
775 and then End_Of_File
(Session
);
782 return End_Of_Data
(Cur_Session
);
790 (Session
: Session_Type
) return Boolean
793 return Text_IO
.End_Of_File
(Session
.Data
.Current_File
);
800 return End_Of_File
(Cur_Session
);
809 Session
: Session_Type
) return String
811 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
814 if Rank
> Number_Of_Fields
(Session
) then
816 (Field_Error
'Identity,
817 "Field number" & Count
'Image (Rank
) & " does not exist.",
822 -- Returns the whole line, this is what $0 does under Session_Type
824 return To_String
(Session
.Data
.Current_Line
);
827 return Slice
(Session
.Data
.Current_Line
,
828 Fields
.Table
(Positive (Rank
)).First
,
829 Fields
.Table
(Positive (Rank
)).Last
);
834 (Rank
: Count
) return String
837 return Field
(Rank
, Cur_Session
);
842 Session
: Session_Type
) return Integer
845 return Integer'Value (Field
(Rank
, Session
));
848 when Constraint_Error
=>
850 (Field_Error
'Identity,
851 "Field number" & Count
'Image (Rank
)
852 & " cannot be converted to an integer.",
857 (Rank
: Count
) return Integer
860 return Field
(Rank
, Cur_Session
);
865 Session
: Session_Type
) return Float
868 return Float'Value (Field
(Rank
, Session
));
871 when Constraint_Error
=>
873 (Field_Error
'Identity,
874 "Field number" & Count
'Image (Rank
)
875 & " cannot be converted to a float.",
880 (Rank
: Count
) return Float
883 return Field
(Rank
, Cur_Session
);
891 (Session
: Session_Type
) return String
893 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
896 if Session
.Data
.File_Index
= 0 then
899 return Files
.Table
(Session
.Data
.File_Index
).all;
907 return File
(Cur_Session
);
914 procedure For_Every_Line
915 (Separators
: String := Use_Current
;
916 Filename
: String := Use_Current
;
917 Callbacks
: Callback_Mode
:= None
;
918 Session
: Session_Type
)
923 Open
(Separators
, Filename
, Session
);
925 while not End_Of_Data
(Session
) loop
927 Split_Line
(Session
);
929 if Callbacks
in Only
.. Pass_Through
then
933 Discard
:= Apply_Filters
(Session
);
937 if Callbacks
/= Only
then
947 procedure For_Every_Line_Current_Session
948 (Separators
: String := Use_Current
;
949 Filename
: String := Use_Current
;
950 Callbacks
: Callback_Mode
:= None
)
952 procedure Do_It
is new For_Every_Line
(Action
);
954 Do_It
(Separators
, Filename
, Callbacks
, Cur_Session
);
955 end For_Every_Line_Current_Session
;
962 (Callbacks
: Callback_Mode
:= None
;
963 Session
: Session_Type
)
965 Filter_Active
: Boolean;
968 if not Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
974 Split_Line
(Session
);
981 Filter_Active
:= Apply_Filters
(Session
);
982 exit when not Filter_Active
;
985 Filter_Active
:= Apply_Filters
(Session
);
992 (Callbacks
: Callback_Mode
:= None
)
995 Get_Line
(Callbacks
, Cur_Session
);
998 ----------------------
999 -- Number_Of_Fields --
1000 ----------------------
1002 function Number_Of_Fields
1003 (Session
: Session_Type
) return Count
1006 return Count
(Field_Table
.Last
(Session
.Data
.Fields
));
1007 end Number_Of_Fields
;
1009 function Number_Of_Fields
1013 return Number_Of_Fields
(Cur_Session
);
1014 end Number_Of_Fields
;
1016 --------------------------
1017 -- Number_Of_File_Lines --
1018 --------------------------
1020 function Number_Of_File_Lines
1021 (Session
: Session_Type
) return Count
1024 return Count
(Session
.Data
.FNR
);
1025 end Number_Of_File_Lines
;
1027 function Number_Of_File_Lines
1031 return Number_Of_File_Lines
(Cur_Session
);
1032 end Number_Of_File_Lines
;
1034 ---------------------
1035 -- Number_Of_Files --
1036 ---------------------
1038 function Number_Of_Files
1039 (Session
: Session_Type
) return Natural
1041 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
1043 return File_Table
.Last
(Files
);
1044 end Number_Of_Files
;
1046 function Number_Of_Files
1050 return Number_Of_Files
(Cur_Session
);
1051 end Number_Of_Files
;
1053 ---------------------
1054 -- Number_Of_Lines --
1055 ---------------------
1057 function Number_Of_Lines
1058 (Session
: Session_Type
) return Count
1061 return Count
(Session
.Data
.NR
);
1062 end Number_Of_Lines
;
1064 function Number_Of_Lines
1068 return Number_Of_Lines
(Cur_Session
);
1069 end Number_Of_Lines
;
1076 (Separators
: String := Use_Current
;
1077 Filename
: String := Use_Current
;
1078 Session
: Session_Type
)
1081 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
1082 raise Session_Error
;
1085 if Filename
/= Use_Current
then
1086 File_Table
.Init
(Session
.Data
.Files
);
1087 Add_File
(Filename
, Session
);
1090 if Separators
/= Use_Current
then
1091 Set_Field_Separators
(Separators
, Session
);
1094 Open_Next_File
(Session
);
1102 (Separators
: String := Use_Current
;
1103 Filename
: String := Use_Current
)
1106 Open
(Separators
, Filename
, Cur_Session
);
1109 --------------------
1110 -- Open_Next_File --
1111 --------------------
1113 procedure Open_Next_File
1114 (Session
: Session_Type
)
1116 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
1119 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
1120 Text_IO
.Close
(Session
.Data
.Current_File
);
1123 Session
.Data
.File_Index
:= Session
.Data
.File_Index
+ 1;
1125 -- If there are no mores file in the table, raise End_Error
1127 if Session
.Data
.File_Index
> File_Table
.Last
(Files
) then
1132 (File
=> Session
.Data
.Current_File
,
1133 Name
=> Files
.Table
(Session
.Data
.File_Index
).all,
1134 Mode
=> Text_IO
.In_File
);
1142 (Separators
: String := Use_Current
;
1143 Filename
: String := Use_Current
;
1144 Session
: Session_Type
)
1146 Filter_Active
: Boolean;
1147 pragma Unreferenced
(Filter_Active
);
1150 Open
(Separators
, Filename
, Session
);
1152 while not End_Of_Data
(Session
) loop
1153 Get_Line
(None
, Session
);
1154 Filter_Active
:= Apply_Filters
(Session
);
1161 (Separators
: String := Use_Current
;
1162 Filename
: String := Use_Current
)
1165 Parse
(Separators
, Filename
, Cur_Session
);
1168 ---------------------
1169 -- Raise_With_Info --
1170 ---------------------
1172 procedure Raise_With_Info
1173 (E
: Exceptions
.Exception_Id
;
1175 Session
: Session_Type
)
1177 function Filename
return String;
1178 -- Returns current filename and "??" if this information is not
1181 function Line
return String;
1182 -- Returns current line number without the leading space
1188 function Filename
return String is
1189 File
: constant String := AWK
.File
(Session
);
1202 function Line
return String is
1203 L
: constant String := Natural'Image (Session
.Data
.FNR
);
1205 return L
(2 .. L
'Last);
1208 -- Start of processing for Raise_With_Info
1211 Exceptions
.Raise_Exception
1213 '[' & Filename
& ':' & Line
& "] " & Message
);
1214 raise Constraint_Error
; -- to please GNAT as this is a No_Return proc
1215 end Raise_With_Info
;
1221 procedure Read_Line
(Session
: Session_Type
) is
1223 function Read_Line
return String;
1224 -- Read a line in the current file. This implementation is recursive
1225 -- and does not have a limitation on the line length.
1227 NR
: Natural renames Session
.Data
.NR
;
1228 FNR
: Natural renames Session
.Data
.FNR
;
1234 function Read_Line
return String is
1235 Buffer
: String (1 .. 1_024
);
1239 Text_IO
.Get_Line
(Session
.Data
.Current_File
, Buffer
, Last
);
1241 if Last
= Buffer
'Last then
1242 return Buffer
& Read_Line
;
1244 return Buffer
(1 .. Last
);
1248 -- Start of processing for Read_Line
1251 if End_Of_File
(Session
) then
1252 Open_Next_File
(Session
);
1256 Session
.Data
.Current_Line
:= To_Unbounded_String
(Read_Line
);
1269 Action
: Action_Callback
;
1270 Session
: Session_Type
)
1272 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1273 U_Pattern
: constant Unbounded_String
:= To_Unbounded_String
(Pattern
);
1276 Pattern_Action_Table
.Increment_Last
(Filters
);
1278 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1279 (Pattern
=> new Patterns
.String_Pattern
'(U_Pattern, Field),
1280 Action => new Actions.Simple_Action'(Proc
=> Action
));
1286 Action
: Action_Callback
)
1289 Register
(Field
, Pattern
, Action
, Cur_Session
);
1294 Pattern
: GNAT
.Regpat
.Pattern_Matcher
;
1295 Action
: Action_Callback
;
1296 Session
: Session_Type
)
1298 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1300 A_Pattern
: constant Patterns
.Pattern_Matcher_Access
:=
1301 new Regpat
.Pattern_Matcher
'(Pattern);
1303 Pattern_Action_Table.Increment_Last (Filters);
1305 Filters.Table (Pattern_Action_Table.Last (Filters)) :=
1306 (Pattern => new Patterns.Regexp_Pattern'(A_Pattern
, Field
),
1307 Action
=> new Actions
.Simple_Action
'(Proc => Action));
1312 Pattern : GNAT.Regpat.Pattern_Matcher;
1313 Action : Action_Callback)
1316 Register (Field, Pattern, Action, Cur_Session);
1321 Pattern : GNAT.Regpat.Pattern_Matcher;
1322 Action : Match_Action_Callback;
1323 Session : Session_Type)
1325 Filters : Pattern_Action_Table.Instance renames Session.Data.Filters;
1327 A_Pattern : constant Patterns.Pattern_Matcher_Access :=
1328 new Regpat.Pattern_Matcher'(Pattern
);
1330 Pattern_Action_Table
.Increment_Last
(Filters
);
1332 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1333 (Pattern
=> new Patterns
.Regexp_Pattern
'(A_Pattern, Field),
1334 Action => new Actions.Match_Action'(Proc
=> Action
));
1339 Pattern
: GNAT
.Regpat
.Pattern_Matcher
;
1340 Action
: Match_Action_Callback
)
1343 Register
(Field
, Pattern
, Action
, Cur_Session
);
1347 (Pattern
: Pattern_Callback
;
1348 Action
: Action_Callback
;
1349 Session
: Session_Type
)
1351 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1354 Pattern_Action_Table
.Increment_Last
(Filters
);
1356 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1357 (Pattern
=> new Patterns
.Callback_Pattern
'(Pattern => Pattern),
1358 Action => new Actions.Simple_Action'(Proc
=> Action
));
1362 (Pattern
: Pattern_Callback
;
1363 Action
: Action_Callback
)
1366 Register
(Pattern
, Action
, Cur_Session
);
1370 (Action
: Action_Callback
;
1371 Session
: Session_Type
)
1374 Register
(Always_True
'Access, Action
, Session
);
1378 (Action
: Action_Callback
)
1381 Register
(Action
, Cur_Session
);
1388 procedure Set_Current
(Session
: Session_Type
) is
1390 Cur_Session
.Data
:= Session
.Data
;
1393 --------------------------
1394 -- Set_Field_Separators --
1395 --------------------------
1397 procedure Set_Field_Separators
1398 (Separators
: String := Default_Separators
;
1399 Session
: Session_Type
)
1402 Free
(Session
.Data
.Separators
);
1404 Session
.Data
.Separators
:=
1405 new Split
.Separator
'(Separators'Length, Separators);
1407 -- If there is a current line read, split it according to the new
1410 if Session.Data.Current_Line /= Null_Unbounded_String then
1411 Split_Line (Session);
1413 end Set_Field_Separators;
1415 procedure Set_Field_Separators
1416 (Separators : String := Default_Separators)
1419 Set_Field_Separators (Separators, Cur_Session);
1420 end Set_Field_Separators;
1422 ----------------------
1423 -- Set_Field_Widths --
1424 ----------------------
1426 procedure Set_Field_Widths
1427 (Field_Widths : Widths_Set;
1428 Session : Session_Type)
1431 Free (Session.Data.Separators);
1433 Session.Data.Separators :=
1434 new Split.Column'(Field_Widths
'Length, Field_Widths
);
1436 -- If there is a current line read, split it according to
1437 -- the new separators.
1439 if Session
.Data
.Current_Line
/= Null_Unbounded_String
then
1440 Split_Line
(Session
);
1442 end Set_Field_Widths
;
1444 procedure Set_Field_Widths
1445 (Field_Widths
: Widths_Set
)
1448 Set_Field_Widths
(Field_Widths
, Cur_Session
);
1449 end Set_Field_Widths
;
1455 procedure Split_Line
(Session
: Session_Type
) is
1456 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
1458 Field_Table
.Init
(Fields
);
1459 Split
.Current_Line
(Session
.Data
.Separators
.all, Session
);
1466 function Get_Def
return Session_Data_Access
is
1468 return Def_Session
.Data
;
1475 procedure Set_Cur
is
1477 Cur_Session
.Data
:= Def_Session
.Data
;
1481 -- We have declared two sessions but both should share the same data.
1482 -- The current session must point to the default session as its initial
1483 -- value. So first we release the session data then we set current
1484 -- session data to point to default session data.
1486 Free
(Cur_Session
.Data
);
1487 Cur_Session
.Data
:= Def_Session
.Data
;