1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 2000-2001 Ada Core Technologies, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com). --
33 ------------------------------------------------------------------------------
35 pragma Style_Checks
(All_Checks
);
36 -- Turn off alpha ordering check for subprograms, since we cannot
37 -- Put Finalize and Initialize in alpha order (see comments).
41 with Ada
.Strings
.Unbounded
;
42 with Ada
.Strings
.Fixed
;
43 with Ada
.Strings
.Maps
;
44 with Ada
.Unchecked_Deallocation
;
46 with GNAT
.Directory_Operations
;
47 with GNAT
.Dynamic_Tables
;
50 package body GNAT
.AWK
is
53 use Ada
.Strings
.Unbounded
;
61 type Mode
is abstract tagged null record;
62 -- This is the main type which is declared abstract. This type must be
63 -- derived for each split style.
65 type Mode_Access
is access Mode
'Class;
67 procedure Current_Line
(S
: Mode
; Session
: Session_Type
)
69 -- Split Session's current line using split mode.
71 ------------------------
72 -- Split on separator --
73 ------------------------
75 type Separator
(Size
: Positive) is new Mode
with record
76 Separators
: String (1 .. Size
);
79 procedure Current_Line
81 Session
: Session_Type
);
87 type Column
(Size
: Positive) is new Mode
with record
88 Columns
: Widths_Set
(1 .. Size
);
91 procedure Current_Line
(S
: Column
; Session
: Session_Type
);
95 procedure Free
is new Unchecked_Deallocation
96 (Split
.Mode
'Class, Split
.Mode_Access
);
102 type AWK_File
is access String;
104 package File_Table
is
105 new Dynamic_Tables
(AWK_File
, Natural, 1, 5, 50);
106 -- List of filename associated with a Session.
108 procedure Free
is new Unchecked_Deallocation
(String, AWK_File
);
114 type Field_Slice
is record
118 -- This is a field slice (First .. Last) in session's current line.
120 package Field_Table
is
121 new Dynamic_Tables
(Field_Slice
, Natural, 1, 10, 100);
122 -- List of fields for the current line.
128 -- Define all patterns style : exact string, regular expression, boolean
133 type Pattern
is abstract tagged null record;
134 -- This is the main type which is declared abstract. This type must be
135 -- derived for each patterns style.
137 type Pattern_Access
is access Pattern
'Class;
141 Session
: Session_Type
)
144 -- Returns True if P match for the current session and False otherwise.
146 procedure Release
(P
: in out Pattern
);
147 -- Release memory used by the pattern structure.
149 --------------------------
150 -- Exact string pattern --
151 --------------------------
153 type String_Pattern
is new Pattern
with record
154 Str
: Unbounded_String
;
160 Session
: Session_Type
)
163 --------------------------------
164 -- Regular expression pattern --
165 --------------------------------
167 type Pattern_Matcher_Access
is access Regpat
.Pattern_Matcher
;
169 type Regexp_Pattern
is new Pattern
with record
170 Regx
: Pattern_Matcher_Access
;
176 Session
: Session_Type
)
179 procedure Release
(P
: in out Regexp_Pattern
);
181 ------------------------------
182 -- Boolean function pattern --
183 ------------------------------
185 type Callback_Pattern
is new Pattern
with record
186 Pattern
: Pattern_Callback
;
190 (P
: Callback_Pattern
;
191 Session
: Session_Type
)
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
)
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 Initialize
(Session
: in out Session_Type
) is
287 Session
.Data
:= new Session_Data
;
289 -- Initialize separators
291 Session
.Data
.Separators
:=
292 new Split
.Separator
'(Default_Separators'Length, Default_Separators);
294 -- Initialize all tables
296 File_Table.Init (Session.Data.Files);
297 Field_Table.Init (Session.Data.Fields);
298 Pattern_Action_Table.Init (Session.Data.Filters);
301 -----------------------
302 -- Session Variables --
303 -----------------------
305 -- These must come after the body of Initialize, since they make
306 -- implicit calls to Initialize at elaboration time.
308 Def_Session : Session_Type;
309 Cur_Session : Session_Type;
315 -- Note: Finalize must come after Initialize and the definition
316 -- of the Def_Session and Cur_Session variables, since it references
319 procedure Finalize (Session : in out Session_Type) is
321 -- We release the session data only if it is not the default session.
323 if Session.Data /= Def_Session.Data then
326 -- Since we have closed the current session, set it to point
327 -- now to the default session.
329 Cur_Session.Data := Def_Session.Data;
333 ----------------------
334 -- Private Services --
335 ----------------------
337 function Always_True return Boolean;
338 -- A function that always returns True.
340 function Apply_Filters
341 (Session : Session_Type := Current_Session)
343 -- Apply any filters for which the Pattern is True for Session. It returns
344 -- True if a least one filters has been applied (i.e. associated action
345 -- callback has been called).
347 procedure Open_Next_File
348 (Session : Session_Type := Current_Session);
349 pragma Inline (Open_Next_File);
350 -- Open next file for Session closing current file if needed. It raises
351 -- End_Error if there is no more file in the table.
353 procedure Raise_With_Info
354 (E : Exceptions.Exception_Id;
356 Session : Session_Type);
357 pragma No_Return (Raise_With_Info);
358 -- Raises exception E with the message prepended with the current line
359 -- number and the filename if possible.
361 procedure Read_Line (Session : Session_Type);
362 -- Read a line for the Session and set Current_Line.
364 procedure Split_Line (Session : Session_Type);
365 -- Split session's Current_Line according to the session separators and
366 -- set the Fields table. This procedure can be called at any time.
368 ----------------------
369 -- Private Packages --
370 ----------------------
376 package body Actions is
384 Session : Session_Type)
396 Session : Session_Type)
399 A.Proc (Session.Data.Matches);
408 package body Patterns is
416 Session : Session_Type)
420 return P.Str = Field (P.Rank, Session);
429 Session : Session_Type)
432 use type Regpat.Match_Location;
436 (P.Regx.all, Field (P.Rank, Session), Session.Data.Matches);
437 return Session.Data.Matches (0) /= Regpat.No_Match;
445 (P : Callback_Pattern;
446 Session : Session_Type)
450 return P.Pattern.all;
457 procedure Release (P : in out Pattern) is
466 procedure Release (P : in out Regexp_Pattern) is
467 procedure Free is new Unchecked_Deallocation
468 (Regpat.Pattern_Matcher, Pattern_Matcher_Access);
480 package body Split is
488 procedure Current_Line (S : Separator; Session : Session_Type) is
489 Line : constant String := To_String (Session.Data.Current_Line);
490 Fields : Field_Table.Instance renames Session.Data.Fields;
495 Seps : Maps.Character_Set := Maps.To_Set (S.Separators);
498 -- First field start here
502 -- Record the first field start position which is the first character
505 Field_Table.Increment_Last (Fields);
506 Fields.Table (Field_Table.Last (Fields)).First := Start;
509 -- Look for next separator
512 (Source => Line (Start .. Line'Last),
517 Fields.Table (Field_Table.Last (Fields)).Last := Stop - 1;
519 -- if separators are set to the default (space and tab) we skip
520 -- all spaces and tabs following current field.
522 if S.Separators = Default_Separators then
524 (Line (Stop + 1 .. Line'Last),
525 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 := Current_Session)
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.",
611 Number_Of_Files_Added
: out Natural;
612 Session
: Session_Type
:= Current_Session
)
614 use Directory_Operations
;
617 Filename
: String (1 .. 200);
621 Number_Of_Files_Added
:= 0;
623 Open
(Dir
, Directory
);
626 Read
(Dir
, Filename
, Last
);
629 Add_File
(Filename
(1 .. Last
), Session
);
630 Number_Of_Files_Added
:= Number_Of_Files_Added
+ 1;
638 (File_Error
'Identity,
639 "Error scaning directory " & Directory
640 & " for files " & Filenames
& '.',
648 function Always_True
return Boolean is
657 function Apply_Filters
658 (Session
: Session_Type
:= Current_Session
)
661 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
662 Results
: Boolean := False;
665 -- Iterate through the filters table, if pattern match call action.
667 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
668 if Patterns
.Match
(Filters
.Table
(F
).Pattern
.all, Session
) then
670 Actions
.Call
(Filters
.Table
(F
).Action
.all, Session
);
681 procedure Close
(Session
: Session_Type
) is
682 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
683 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
686 -- Close current file if needed
688 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
689 Text_IO
.Close
(Session
.Data
.Current_File
);
692 -- Release separators
694 Free
(Session
.Data
.Separators
);
696 -- Release Filters table
698 for F
in 1 .. Pattern_Action_Table
.Last
(Filters
) loop
699 Patterns
.Release
(Filters
.Table
(F
).Pattern
.all);
700 Free
(Filters
.Table
(F
).Pattern
);
701 Free
(Filters
.Table
(F
).Action
);
704 for F
in 1 .. File_Table
.Last
(Files
) loop
705 Free
(Files
.Table
(F
));
708 File_Table
.Set_Last
(Session
.Data
.Files
, 0);
709 Field_Table
.Set_Last
(Session
.Data
.Fields
, 0);
710 Pattern_Action_Table
.Set_Last
(Session
.Data
.Filters
, 0);
712 Session
.Data
.NR
:= 0;
713 Session
.Data
.FNR
:= 0;
714 Session
.Data
.File_Index
:= 0;
715 Session
.Data
.Current_Line
:= Null_Unbounded_String
;
718 ---------------------
719 -- Current_Session --
720 ---------------------
722 function Current_Session
return Session_Type
is
727 ---------------------
728 -- Default_Session --
729 ---------------------
731 function Default_Session
return Session_Type
is
740 function Discrete_Field
742 Session
: Session_Type
:= Current_Session
)
746 return Discrete
'Value (Field
(Rank
, Session
));
754 (Session
: Session_Type
:= Current_Session
)
758 return Session
.Data
.File_Index
= File_Table
.Last
(Session
.Data
.Files
)
759 and then End_Of_File
(Session
);
767 (Session
: Session_Type
:= Current_Session
)
771 return Text_IO
.End_Of_File
(Session
.Data
.Current_File
);
780 Session
: Session_Type
:= Current_Session
)
783 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
786 if Rank
> Number_Of_Fields
(Session
) then
788 (Field_Error
'Identity,
789 "Field number" & Count
'Image (Rank
) & " does not exist.",
794 -- Returns the whole line, this is what $0 does under Session_Type.
796 return To_String
(Session
.Data
.Current_Line
);
799 return Slice
(Session
.Data
.Current_Line
,
800 Fields
.Table
(Positive (Rank
)).First
,
801 Fields
.Table
(Positive (Rank
)).Last
);
807 Session
: Session_Type
:= Current_Session
)
811 return Integer'Value (Field
(Rank
, Session
));
814 when Constraint_Error
=>
816 (Field_Error
'Identity,
817 "Field number" & Count
'Image (Rank
)
818 & " cannot be converted to an integer.",
824 Session
: Session_Type
:= Current_Session
)
828 return Float'Value (Field
(Rank
, Session
));
831 when Constraint_Error
=>
833 (Field_Error
'Identity,
834 "Field number" & Count
'Image (Rank
)
835 & " cannot be converted to a float.",
844 (Session
: Session_Type
:= Current_Session
)
847 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
850 if Session
.Data
.File_Index
= 0 then
853 return Files
.Table
(Session
.Data
.File_Index
).all;
861 procedure For_Every_Line
862 (Separators
: String := Use_Current
;
863 Filename
: String := Use_Current
;
864 Callbacks
: Callback_Mode
:= None
;
865 Session
: Session_Type
:= Current_Session
)
867 Filter_Active
: Boolean;
871 Open
(Separators
, Filename
, Session
);
873 while not End_Of_Data
(Session
) loop
875 Split_Line
(Session
);
877 if Callbacks
in Only
.. Pass_Through
then
878 Filter_Active
:= Apply_Filters
(Session
);
881 if Callbacks
/= Only
then
896 (Callbacks
: Callback_Mode
:= None
;
897 Session
: Session_Type
:= Current_Session
)
899 Filter_Active
: Boolean;
902 if not Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
908 Split_Line
(Session
);
910 if Callbacks
in Only
.. Pass_Through
then
911 Filter_Active
:= Apply_Filters
(Session
);
914 exit when Callbacks
= None
915 or else Callbacks
= Pass_Through
916 or else (Callbacks
= Only
and then not Filter_Active
);
921 ----------------------
922 -- Number_Of_Fields --
923 ----------------------
925 function Number_Of_Fields
926 (Session
: Session_Type
:= Current_Session
)
930 return Count
(Field_Table
.Last
(Session
.Data
.Fields
));
931 end Number_Of_Fields
;
933 --------------------------
934 -- Number_Of_File_Lines --
935 --------------------------
937 function Number_Of_File_Lines
938 (Session
: Session_Type
:= Current_Session
)
942 return Count
(Session
.Data
.FNR
);
943 end Number_Of_File_Lines
;
945 ---------------------
946 -- Number_Of_Files --
947 ---------------------
949 function Number_Of_Files
950 (Session
: Session_Type
:= Current_Session
)
953 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
956 return File_Table
.Last
(Files
);
959 ---------------------
960 -- Number_Of_Lines --
961 ---------------------
963 function Number_Of_Lines
964 (Session
: Session_Type
:= Current_Session
)
968 return Count
(Session
.Data
.NR
);
976 (Separators
: String := Use_Current
;
977 Filename
: String := Use_Current
;
978 Session
: Session_Type
:= Current_Session
)
981 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
985 if Filename
/= Use_Current
then
986 File_Table
.Init
(Session
.Data
.Files
);
987 Add_File
(Filename
, Session
);
990 if Separators
/= Use_Current
then
991 Set_Field_Separators
(Separators
, Session
);
994 Open_Next_File
(Session
);
1001 --------------------
1002 -- Open_Next_File --
1003 --------------------
1005 procedure Open_Next_File
1006 (Session
: Session_Type
:= Current_Session
)
1008 Files
: File_Table
.Instance
renames Session
.Data
.Files
;
1011 if Text_IO
.Is_Open
(Session
.Data
.Current_File
) then
1012 Text_IO
.Close
(Session
.Data
.Current_File
);
1015 Session
.Data
.File_Index
:= Session
.Data
.File_Index
+ 1;
1017 -- If there are no mores file in the table, raise End_Error
1019 if Session
.Data
.File_Index
> File_Table
.Last
(Files
) then
1024 (File
=> Session
.Data
.Current_File
,
1025 Name
=> Files
.Table
(Session
.Data
.File_Index
).all,
1026 Mode
=> Text_IO
.In_File
);
1034 (Separators
: String := Use_Current
;
1035 Filename
: String := Use_Current
;
1036 Session
: Session_Type
:= Current_Session
)
1038 Filter_Active
: Boolean;
1040 Open
(Separators
, Filename
, Session
);
1042 while not End_Of_Data
(Session
) loop
1043 Get_Line
(None
, Session
);
1044 Filter_Active
:= Apply_Filters
(Session
);
1050 ---------------------
1051 -- Raise_With_Info --
1052 ---------------------
1054 procedure Raise_With_Info
1055 (E
: Exceptions
.Exception_Id
;
1057 Session
: Session_Type
)
1059 function Filename
return String;
1060 -- Returns current filename and "??" if the informations is not
1063 function Line
return String;
1064 -- Returns current line number without the leading space
1070 function Filename
return String is
1071 File
: constant String := AWK
.File
(Session
);
1085 function Line
return String is
1086 L
: constant String := Natural'Image (Session
.Data
.FNR
);
1089 return L
(2 .. L
'Last);
1092 -- Start of processing for Raise_With_Info
1095 Exceptions
.Raise_Exception
1097 '[' & Filename
& ':' & Line
& "] " & Message
);
1098 raise Constraint_Error
; -- to please GNAT as this is a No_Return proc
1099 end Raise_With_Info
;
1105 procedure Read_Line
(Session
: Session_Type
) is
1107 function Read_Line
return String;
1108 -- Read a line in the current file. This implementation is recursive
1109 -- and does not have a limitation on the line length.
1111 NR
: Natural renames Session
.Data
.NR
;
1112 FNR
: Natural renames Session
.Data
.FNR
;
1114 function Read_Line
return String is
1115 Buffer
: String (1 .. 1_024
);
1119 Text_IO
.Get_Line
(Session
.Data
.Current_File
, Buffer
, Last
);
1121 if Last
= Buffer
'Last then
1122 return Buffer
& Read_Line
;
1124 return Buffer
(1 .. Last
);
1128 -- Start of processing for Read_Line
1131 if End_Of_File
(Session
) then
1132 Open_Next_File
(Session
);
1136 Session
.Data
.Current_Line
:= To_Unbounded_String
(Read_Line
);
1149 Action
: Action_Callback
;
1150 Session
: Session_Type
:= Current_Session
)
1152 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1153 U_Pattern
: constant Unbounded_String
:= To_Unbounded_String
(Pattern
);
1156 Pattern_Action_Table
.Increment_Last
(Filters
);
1158 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1159 (Pattern
=> new Patterns
.String_Pattern
'(U_Pattern, Field),
1160 Action => new Actions.Simple_Action'(Proc
=> Action
));
1165 Pattern
: GNAT
.Regpat
.Pattern_Matcher
;
1166 Action
: Action_Callback
;
1167 Session
: Session_Type
:= Current_Session
)
1169 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1171 A_Pattern
: Patterns
.Pattern_Matcher_Access
:=
1172 new Regpat
.Pattern_Matcher
'(Pattern);
1174 Pattern_Action_Table.Increment_Last (Filters);
1176 Filters.Table (Pattern_Action_Table.Last (Filters)) :=
1177 (Pattern => new Patterns.Regexp_Pattern'(A_Pattern
, Field
),
1178 Action
=> new Actions
.Simple_Action
'(Proc => Action));
1183 Pattern : GNAT.Regpat.Pattern_Matcher;
1184 Action : Match_Action_Callback;
1185 Session : Session_Type := Current_Session)
1187 Filters : Pattern_Action_Table.Instance renames Session.Data.Filters;
1189 A_Pattern : Patterns.Pattern_Matcher_Access :=
1190 new Regpat.Pattern_Matcher'(Pattern
);
1192 Pattern_Action_Table
.Increment_Last
(Filters
);
1194 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1195 (Pattern
=> new Patterns
.Regexp_Pattern
'(A_Pattern, Field),
1196 Action => new Actions.Match_Action'(Proc
=> Action
));
1200 (Pattern
: Pattern_Callback
;
1201 Action
: Action_Callback
;
1202 Session
: Session_Type
:= Current_Session
)
1204 Filters
: Pattern_Action_Table
.Instance
renames Session
.Data
.Filters
;
1207 Pattern_Action_Table
.Increment_Last
(Filters
);
1209 Filters
.Table
(Pattern_Action_Table
.Last
(Filters
)) :=
1210 (Pattern
=> new Patterns
.Callback_Pattern
'(Pattern => Pattern),
1211 Action => new Actions.Simple_Action'(Proc
=> Action
));
1215 (Action
: Action_Callback
;
1216 Session
: Session_Type
:= Current_Session
)
1219 Register
(Always_True
'Access, Action
, Session
);
1226 procedure Set_Current
(Session
: Session_Type
) is
1228 Cur_Session
.Data
:= Session
.Data
;
1231 --------------------------
1232 -- Set_Field_Separators --
1233 --------------------------
1235 procedure Set_Field_Separators
1236 (Separators
: String := Default_Separators
;
1237 Session
: Session_Type
:= Current_Session
)
1240 Free
(Session
.Data
.Separators
);
1242 Session
.Data
.Separators
:=
1243 new Split
.Separator
'(Separators'Length, Separators);
1245 -- If there is a current line read, split it according to the new
1248 if Session.Data.Current_Line /= Null_Unbounded_String then
1249 Split_Line (Session);
1251 end Set_Field_Separators;
1253 ----------------------
1254 -- Set_Field_Widths --
1255 ----------------------
1257 procedure Set_Field_Widths
1258 (Field_Widths : Widths_Set;
1259 Session : Session_Type := Current_Session) is
1262 Free (Session.Data.Separators);
1264 Session.Data.Separators :=
1265 new Split.Column'(Field_Widths
'Length, Field_Widths
);
1267 -- If there is a current line read, split it according to
1268 -- the new separators.
1270 if Session
.Data
.Current_Line
/= Null_Unbounded_String
then
1271 Split_Line
(Session
);
1273 end Set_Field_Widths
;
1279 procedure Split_Line
(Session
: Session_Type
) is
1280 Fields
: Field_Table
.Instance
renames Session
.Data
.Fields
;
1283 Field_Table
.Init
(Fields
);
1285 Split
.Current_Line
(Session
.Data
.Separators
.all, Session
);
1289 -- We have declared two sessions but both should share the same data.
1290 -- The current session must point to the default session as its initial
1291 -- value. So first we release the session data then we set current
1292 -- session data to point to default session data.
1294 Free
(Cur_Session
.Data
);
1295 Cur_Session
.Data
:= Def_Session
.Data
;