bc8cf674fcfe3ad50d75f3860fe97a39f0fa100b
[gcc.git] / gcc / ada / set_targ.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S E T _ T A R G --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2013, Free Software Foundation, Inc. --
10 -- --
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. 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Debug; use Debug;
27 with Get_Targ; use Get_Targ;
28 with Opt; use Opt;
29 with Output; use Output;
30
31 with System; use System;
32 with System.OS_Lib; use System.OS_Lib;
33
34 with Unchecked_Conversion;
35
36 package body Set_Targ is
37
38 ---------------------------------------------
39 -- Data Used to Read/Write target.atp File --
40 ---------------------------------------------
41
42 File_Name : aliased constant String := "target.atp";
43 -- Name of file to read/write
44
45 -- Table of string names written to file
46
47 subtype Str is String;
48
49 S_Bits_BE : constant Str := "Bits_BE";
50 S_Bits_Per_Unit : constant Str := "Bits_Per_Unit";
51 S_Bits_Per_Word : constant Str := "Bits_Per_Word";
52 S_Bytes_BE : constant Str := "Bytes_BE";
53 S_Char_Size : constant Str := "Char_Size";
54 S_Double_Float_Alignment : constant Str := "Double_Float_Alignment";
55 S_Double_Scalar_Alignment : constant Str := "Double_Scalar_Alignment";
56 S_Double_Size : constant Str := "Double_Size";
57 S_Float_Size : constant Str := "Float_Size";
58 S_Float_Words_BE : constant Str := "Float_Words_BE";
59 S_Int_Size : constant Str := "Int_Size";
60 S_Long_Double_Size : constant Str := "Long_Double_Size";
61 S_Long_Long_Size : constant Str := "Long_Long_Size";
62 S_Long_Size : constant Str := "Long_Size";
63 S_Maximum_Alignment : constant Str := "Maximum_Alignment";
64 S_Max_Unaligned_Field : constant Str := "Max_Unaligned_Field";
65 S_Pointer_Size : constant Str := "Pointer_Size";
66 S_Short_Size : constant Str := "Short_Size";
67 S_Strict_Alignment : constant Str := "Strict_Alignment";
68 S_System_Allocator_Alignment : constant Str := "System_Allocator_Alignment";
69 S_Wchar_T_Size : constant Str := "Wchar_T_Size";
70 S_Words_BE : constant Str := "Words_BE";
71
72 -- Table of names
73
74 type AStr is access all String;
75
76 DTN : constant array (Nat range <>) of AStr := (
77 S_Bits_BE 'Unrestricted_Access,
78 S_Bits_Per_Unit 'Unrestricted_Access,
79 S_Bits_Per_Word 'Unrestricted_Access,
80 S_Bytes_BE 'Unrestricted_Access,
81 S_Char_Size 'Unrestricted_Access,
82 S_Double_Float_Alignment 'Unrestricted_Access,
83 S_Double_Scalar_Alignment 'Unrestricted_Access,
84 S_Double_Size 'Unrestricted_Access,
85 S_Float_Size 'Unrestricted_Access,
86 S_Float_Words_BE 'Unrestricted_Access,
87 S_Int_Size 'Unrestricted_Access,
88 S_Long_Double_Size 'Unrestricted_Access,
89 S_Long_Long_Size 'Unrestricted_Access,
90 S_Long_Size 'Unrestricted_Access,
91 S_Maximum_Alignment 'Unrestricted_Access,
92 S_Max_Unaligned_Field 'Unrestricted_Access,
93 S_Pointer_Size 'Unrestricted_Access,
94 S_Short_Size 'Unrestricted_Access,
95 S_Strict_Alignment 'Unrestricted_Access,
96 S_System_Allocator_Alignment 'Unrestricted_Access,
97 S_Wchar_T_Size 'Unrestricted_Access,
98 S_Words_BE 'Unrestricted_Access);
99
100 -- Table of corresponding value pointers
101
102 DTV : constant array (Nat range <>) of System.Address := (
103 Bits_BE 'Address,
104 Bits_Per_Unit 'Address,
105 Bits_Per_Word 'Address,
106 Bytes_BE 'Address,
107 Char_Size 'Address,
108 Double_Float_Alignment 'Address,
109 Double_Scalar_Alignment 'Address,
110 Double_Size 'Address,
111 Float_Size 'Address,
112 Float_Words_BE 'Address,
113 Int_Size 'Address,
114 Long_Double_Size 'Address,
115 Long_Long_Size 'Address,
116 Long_Size 'Address,
117 Maximum_Alignment 'Address,
118 Max_Unaligned_Field 'Address,
119 Pointer_Size 'Address,
120 Short_Size 'Address,
121 Strict_Alignment 'Address,
122 System_Allocator_Alignment 'Address,
123 Wchar_T_Size 'Address,
124 Words_BE 'Address);
125
126 DTR : array (Nat range DTV'Range) of Boolean := (others => False);
127 -- Table of flags used to validate that all values are present in file
128
129 -----------------------
130 -- Local Subprograms --
131 -----------------------
132
133 procedure Fail (E : String);
134 pragma No_Return (Fail);
135 -- Terminate program with fatal error message passed as parameter
136
137 procedure Register_Float_Type
138 (Name : C_String;
139 Digs : Natural;
140 Complex : Boolean;
141 Count : Natural;
142 Float_Rep : Float_Rep_Kind;
143 Size : Positive;
144 Alignment : Natural);
145 pragma Convention (C, Register_Float_Type);
146 -- Call back to allow the back end to register available types. This call
147 -- back makes entries in the FPT_Mode_Table for any floating point types
148 -- reported by the back end. Name is the name of the type as a normal
149 -- format Null-terminated string. Digs is the number of digits, where 0
150 -- means it is not a fpt type (ignored during registration). Complex is
151 -- non-zero if the type has real and imaginary parts (also ignored during
152 -- registration). Count is the number of elements in a vector type (zero =
153 -- not a vector, registration ignores vectors). Float_Rep shows the kind of
154 -- floating-point type, and Size/Alignment are the size/alignment in bits.
155 --
156 -- So to summarize, the only types that are actually registered have Digs
157 -- non-zero, Complex zero (false), and Count zero (not a vector).
158
159 ----------
160 -- Fail --
161 ----------
162
163 procedure Fail (E : String) is
164 E_Fatal : constant := 4;
165 -- Code for fatal error
166 begin
167 Write_Str (E);
168 Write_Eol;
169 OS_Exit (E_Fatal);
170 end Fail;
171
172 -------------------------
173 -- Register_Float_Type --
174 -------------------------
175
176 procedure Register_Float_Type
177 (Name : C_String;
178 Digs : Natural;
179 Complex : Boolean;
180 Count : Natural;
181 Float_Rep : Float_Rep_Kind;
182 Size : Positive;
183 Alignment : Natural)
184 is
185 T : String (1 .. Name'Length);
186 Last : Natural := 0;
187
188 procedure Dump;
189 -- Dump information given by the back end for the type to register
190
191 ----------
192 -- Dump --
193 ----------
194
195 procedure Dump is
196 begin
197 Write_Str ("type " & T (1 .. Last) & " is ");
198
199 if Count > 0 then
200 Write_Str ("array (1 .. ");
201 Write_Int (Int (Count));
202
203 if Complex then
204 Write_Str (", 1 .. 2");
205 end if;
206
207 Write_Str (") of ");
208
209 elsif Complex then
210 Write_Str ("array (1 .. 2) of ");
211 end if;
212
213 if Digs > 0 then
214 Write_Str ("digits ");
215 Write_Int (Int (Digs));
216 Write_Line (";");
217
218 Write_Str ("pragma Float_Representation (");
219
220 case Float_Rep is
221 when IEEE_Binary =>
222 Write_Str ("IEEE");
223
224 when VAX_Native =>
225 case Digs is
226 when 6 =>
227 Write_Str ("VAXF");
228
229 when 9 =>
230 Write_Str ("VAXD");
231
232 when 15 =>
233 Write_Str ("VAXG");
234
235 when others =>
236 Write_Str ("VAX_");
237 Write_Int (Int (Digs));
238 end case;
239
240 when AAMP => Write_Str ("AAMP");
241 end case;
242
243 Write_Line (", " & T (1 .. Last) & ");");
244
245 else
246 Write_Str ("mod 2**");
247 Write_Int (Int (Size / Positive'Max (1, Count)));
248 Write_Line (";");
249 end if;
250
251 Write_Str ("for " & T (1 .. Last) & "'Size use ");
252 Write_Int (Int (Size));
253 Write_Line (";");
254
255 Write_Str ("for " & T (1 .. Last) & "'Alignment use ");
256 Write_Int (Int (Alignment / 8));
257 Write_Line (";");
258 Write_Eol;
259 end Dump;
260
261 -- Start of processing for Register_Float_Type
262
263 begin
264 -- Acquire name
265
266 for J in T'Range loop
267 T (J) := Name (Name'First + J - 1);
268
269 if T (J) = ASCII.NUL then
270 Last := J - 1;
271 exit;
272 end if;
273 end loop;
274
275 -- Dump info if debug flag set
276
277 if Debug_Flag_Dot_B then
278 Dump;
279 end if;
280
281 -- Acquire entry if non-vector non-complex fpt type (digits non-zero)
282
283 if Digs > 0 and then not Complex and then Count = 0 then
284 Num_FPT_Modes := Num_FPT_Modes + 1;
285 FPT_Mode_Table (Num_FPT_Modes) :=
286 (NAME => new String'(T (1 .. Last)),
287 DIGS => Digs,
288 FLOAT_REP => Float_Rep,
289 SIZE => Size,
290 ALIGNMENT => Alignment);
291 end if;
292 end Register_Float_Type;
293
294 -----------------------------------
295 -- Write_Target_Dependent_Values --
296 -----------------------------------
297
298 -- We do this at the System.Os_Lib level, since we have to do the read at
299 -- that level anyway, so it is easier and more consistent to follow the
300 -- same path for the write.
301
302 procedure Write_Target_Dependent_Values is
303 Fdesc : File_Descriptor;
304 OK : Boolean;
305
306 Buffer : String (1 .. 80);
307 Buflen : Natural;
308 -- Buffer used to build line one of file
309
310 type ANat is access all Natural;
311 -- Pointer to Nat or Pos value (it is harmless to treat Pos values and
312 -- Nat values as Natural via Unchecked_Conversion).
313
314 function To_ANat is new Unchecked_Conversion (Address, ANat);
315
316 procedure AddC (C : Character);
317 -- Add one character to buffer
318
319 procedure AddN (N : Natural);
320 -- Add representation of integer N to Buffer, updating Buflen. N
321 -- must be less than 1000, and output is 3 characters with leading
322 -- spaces as needed.
323
324 procedure Write_Line;
325 -- Output contents of Buffer (1 .. Buflen) followed by a New_Line,
326 -- and set Buflen back to zero, ready to write next line.
327
328 ----------
329 -- AddC --
330 ----------
331
332 procedure AddC (C : Character) is
333 begin
334 Buflen := Buflen + 1;
335 Buffer (Buflen) := C;
336 end AddC;
337
338 ----------
339 -- AddN --
340 ----------
341
342 procedure AddN (N : Natural) is
343 begin
344 if N > 999 then
345 raise Program_Error;
346 end if;
347
348 if N > 99 then
349 AddC (Character'Val (48 + N / 100));
350 else
351 AddC (' ');
352 end if;
353
354 if N > 9 then
355 AddC (Character'Val (48 + N / 10 mod 10));
356 else
357 AddC (' ');
358 end if;
359
360 AddC (Character'Val (48 + N mod 10));
361 end AddN;
362
363 ----------------
364 -- Write_Line --
365 ----------------
366
367 procedure Write_Line is
368 begin
369 AddC (ASCII.LF);
370
371 if Buflen /= Write (Fdesc, Buffer'Address, Buflen) then
372 Delete_File (File_Name'Address, OK);
373 Fail ("disk full writing target.atp");
374 end if;
375
376 Buflen := 0;
377 end Write_Line;
378
379 -- Start of processing for Write_Target_Dependent_Values
380
381 begin
382 Fdesc := Create_File (File_Name'Address, Text);
383
384 if Fdesc = Invalid_FD then
385 Fail ("cannot create target.atp");
386 end if;
387
388 -- Loop through values
389
390 for J in DTN'Range loop
391
392 -- Output name
393
394 Buflen := DTN (J)'Length;
395 Buffer (1 .. Buflen) := DTN (J).all;
396
397 -- Line up values
398
399 while Buflen < 26 loop
400 AddC (' ');
401 end loop;
402
403 AddC (' ');
404 AddC (' ');
405
406 -- Output value and write line
407
408 AddN (To_ANat (DTV (J)).all);
409 Write_Line;
410 end loop;
411
412 -- Blank line to separate sections
413
414 Write_Line;
415
416 -- Write lines for registered FPT types
417
418 for J in 1 .. Num_FPT_Modes loop
419 declare
420 E : FPT_Mode_Entry renames FPT_Mode_Table (J);
421 begin
422 Buflen := E.NAME'Last;
423 Buffer (1 .. Buflen) := E.NAME.all;
424
425 -- Pad out to line up values
426
427 while Buflen < 11 loop
428 AddC (' ');
429 end loop;
430
431 AddC (' ');
432 AddC (' ');
433
434 AddN (E.DIGS);
435 AddC (' ');
436 AddC (' ');
437
438 case E.FLOAT_REP is
439 when IEEE_Binary =>
440 AddC ('I');
441 when VAX_Native =>
442 AddC ('V');
443 when AAMP =>
444 AddC ('A');
445 end case;
446
447 AddC (' ');
448
449 AddN (E.SIZE);
450 AddC (' ');
451
452 AddN (E.ALIGNMENT);
453 Write_Line;
454 end;
455 end loop;
456
457 -- Close file
458
459 Close (Fdesc, OK);
460
461 if not OK then
462 Fail ("disk full writing target.atp");
463 end if;
464 end Write_Target_Dependent_Values;
465
466 -- Package Initialization, set target dependent values. This must be done
467 -- early on, before we start accessing various compiler packages, since
468 -- these values are used all over the place.
469
470 begin
471 -- First step: see if the -gnateT switch is present. As we have noted,
472 -- this has to be done very early, so can not depend on the normal circuit
473 -- for reading switches and setting switches in Opt. The following code
474 -- will set Opt.Target_Dependent_Info_Read if an option starting -gnateT
475 -- is present in the options string.
476
477 declare
478 type Arg_Array is array (Nat) of Big_String_Ptr;
479 type Arg_Array_Ptr is access Arg_Array;
480 -- Types to access compiler arguments
481
482 save_argc : Nat;
483 pragma Import (C, save_argc);
484 -- Saved value of argc (number of arguments), imported from misc.c
485
486 save_argv : Arg_Array_Ptr;
487 pragma Import (C, save_argv);
488 -- Saved value of argv (argument pointers), imported from misc.c
489
490 begin
491 -- Loop through arguments looking for -gnateT, also look for -gnatd.b
492
493 for Arg in 1 .. save_argc - 1 loop
494 declare
495 Argv_Ptr : constant Big_String_Ptr := save_argv (Arg);
496 begin
497
498 -- ??? Is there no problem accessing at indices 1 to 7 or 8
499 -- without first checking if the length of the underlying string
500 -- may be smaller? See back_end.adb for an example where function
501 -- Len_Arg is used to retrieve this length.
502
503 if Argv_Ptr (1 .. 7) = "-gnateT" then
504 Opt.Target_Dependent_Info_Read := True;
505 elsif Argv_Ptr (1 .. 8) = "-gnatd.b" then
506 Debug_Flag_Dot_B := True;
507 end if;
508 end;
509 end loop;
510 end;
511
512 -- If the switch is not set, we get all values from the back end
513
514 if not Opt.Target_Dependent_Info_Read then
515
516 -- Set values by direct calls to the back end
517
518 Bits_BE := Get_Bits_BE;
519 Bits_Per_Unit := Get_Bits_Per_Unit;
520 Bits_Per_Word := Get_Bits_Per_Word;
521 Bytes_BE := Get_Bytes_BE;
522 Char_Size := Get_Char_Size;
523 Double_Float_Alignment := Get_Double_Float_Alignment;
524 Double_Scalar_Alignment := Get_Double_Scalar_Alignment;
525 Double_Size := Get_Double_Size;
526 Float_Size := Get_Float_Size;
527 Float_Words_BE := Get_Float_Words_BE;
528 Int_Size := Get_Int_Size;
529 Long_Double_Size := Get_Long_Double_Size;
530 Long_Long_Size := Get_Long_Long_Size;
531 Long_Size := Get_Long_Size;
532 Maximum_Alignment := Get_Maximum_Alignment;
533 Max_Unaligned_Field := Get_Max_Unaligned_Field;
534 Pointer_Size := Get_Pointer_Size;
535 Short_Size := Get_Short_Size;
536 Strict_Alignment := Get_Strict_Alignment;
537 System_Allocator_Alignment := Get_System_Allocator_Alignment;
538 Wchar_T_Size := Get_Wchar_T_Size;
539 Words_BE := Get_Words_BE;
540
541 -- Register floating-point types from the back end
542
543 Register_Back_End_Types (Register_Float_Type'Access);
544
545 -- Case of reading the target dependent values from target.atp
546
547 -- This is bit more complex than might be expected, because it has to be
548 -- done very early. All kinds of packages depend on these values, and we
549 -- can't wait till the normal processing of reading command line switches
550 -- etc to read the file. We do this at the System.OS_Lib level since it is
551 -- too early to be using Osint directly.
552
553 else
554 Read_File : declare
555 File_Desc : File_Descriptor;
556 N : Natural;
557
558 type ANat is access all Natural;
559 -- Pointer to Nat or Pos value (it is harmless to treat Pos values
560 -- as Nat via Unchecked_Conversion).
561
562 function To_ANat is new Unchecked_Conversion (Address, ANat);
563
564 VP : ANat;
565
566 Buffer : String (1 .. 2000);
567 Buflen : Natural;
568 -- File information and length (2000 easily enough!)
569
570 Nam_Buf : String (1 .. 40);
571 Nam_Len : Natural;
572
573 procedure Check_Spaces;
574 -- Checks that we have one or more spaces and skips them
575
576 procedure FailN (S : String);
577 -- Calls Fail prefixing "target.atp: " to the start of the given
578 -- string, and " name" to the end where name is the currently
579 -- gathered name in Nam_Buf, surrounded by quotes.
580
581 procedure Get_Name;
582 -- Scan out name, leaving it in Nam_Buf with Nam_Len set. Calls
583 -- Skip_Spaces to skip any following spaces. Note that the name is
584 -- terminated by a sequence of at least two spaces.
585
586 function Get_Nat return Natural;
587 -- N on entry points to decimal integer, scan out decimal integer
588 -- and return it, leaving N pointing to following space or LF.
589
590 procedure Skip_Spaces;
591 -- Skip past spaces
592
593 ------------------
594 -- Check_Spaces --
595 ------------------
596
597 procedure Check_Spaces is
598 begin
599 if N > Buflen or else Buffer (N) /= ' ' then
600 FailN ("missing space for");
601 end if;
602
603 Skip_Spaces;
604 return;
605 end Check_Spaces;
606
607 -----------
608 -- FailN --
609 -----------
610
611 procedure FailN (S : String) is
612 begin
613 Fail ("target.atp: " & S & " """ & Nam_Buf (1 .. Nam_Len) & '"');
614 end FailN;
615
616 --------------
617 -- Get_Name --
618 --------------
619
620 procedure Get_Name is
621 begin
622 Nam_Len := 0;
623
624 -- Scan out name and put it in Nam_Buf
625
626 loop
627 if N > Buflen or else Buffer (N) = ASCII.LF then
628 FailN ("incorrectly formatted line for");
629 end if;
630
631 -- Name is terminated by two blanks
632
633 exit when N < Buflen and then Buffer (N .. N + 1) = " ";
634
635 Nam_Len := Nam_Len + 1;
636
637 if Nam_Len > Nam_Buf'Last then
638 Fail ("name too long");
639 end if;
640
641 Nam_Buf (Nam_Len) := Buffer (N);
642 N := N + 1;
643 end loop;
644
645 Check_Spaces;
646 end Get_Name;
647
648 -------------
649 -- Get_Nat --
650 -------------
651
652 function Get_Nat return Natural is
653 Result : Natural := 0;
654
655 begin
656 loop
657 if N > Buflen
658 or else Buffer (N) not in '0' .. '9'
659 or else Result > 999
660 then
661 FailN ("bad value for");
662 end if;
663
664 Result := Result * 10 + (Character'Pos (Buffer (N)) - 48);
665 N := N + 1;
666
667 exit when N <= Buflen
668 and then (Buffer (N) = ASCII.LF or else Buffer (N) = ' ');
669 end loop;
670
671 return Result;
672 end Get_Nat;
673
674 -----------------
675 -- Skip_Spaces --
676 -----------------
677
678 procedure Skip_Spaces is
679 begin
680 while N <= Buflen and Buffer (N) = ' ' loop
681 N := N + 1;
682 end loop;
683 end Skip_Spaces;
684
685 -- Start of processing for Read_File
686
687 begin
688 File_Desc := Open_Read ("target.atp", Text);
689
690 if File_Desc = Invalid_FD then
691 Fail ("cannot read target.atp file");
692 end if;
693
694 Buflen := Read (File_Desc, Buffer'Address, Buffer'Length);
695
696 if Buflen = Buffer'Length then
697 Fail ("target.atp file is too long");
698 end if;
699
700 -- Scan through file for properly formatted entries in first section
701
702 N := 1;
703 while N <= Buflen and then Buffer (N) /= ASCII.LF loop
704 Get_Name;
705
706 -- Validate name and get corresponding value pointer
707
708 VP := null;
709
710 for J in DTN'Range loop
711 if DTN (J).all = Nam_Buf (1 .. Nam_Len) then
712 VP := To_ANat (DTV (J));
713 DTR (J) := True;
714 exit;
715 end if;
716 end loop;
717
718 if VP = null then
719 FailN ("unrecognized name");
720 end if;
721
722 -- Scan out value
723
724 VP.all := Get_Nat;
725
726 if N > Buflen or else Buffer (N) /= ASCII.LF then
727 FailN ("misformatted line for");
728 end if;
729
730 N := N + 1; -- skip LF
731 end loop;
732
733 -- Fall through this loop when all lines in first section read.
734 -- Check that values have been supplied for all entries.
735
736 for J in DTR'Range loop
737 if not DTR (J) then
738 Fail ("missing entry in target.atp for " & DTN (J).all);
739 end if;
740 end loop;
741
742 -- Now acquire FPT entries
743
744 if N >= Buflen then
745 Fail ("target.atp is missing entries for FPT modes");
746 end if;
747
748 if Buffer (N) = ASCII.LF then
749 N := N + 1;
750 else
751 Fail ("target.atp is missing blank line");
752 end if;
753
754 Num_FPT_Modes := 0;
755 while N <= Buflen loop
756 Get_Name;
757
758 Num_FPT_Modes := Num_FPT_Modes + 1;
759
760 declare
761 E : FPT_Mode_Entry renames FPT_Mode_Table (Num_FPT_Modes);
762
763 begin
764 E.NAME := new String'(Nam_Buf (1 .. Nam_Len));
765
766 E.DIGS := Get_Nat;
767 Check_Spaces;
768
769 case Buffer (N) is
770 when 'I' =>
771 E.FLOAT_REP := IEEE_Binary;
772 when 'V' =>
773 E.FLOAT_REP := VAX_Native;
774 when 'A' =>
775 E.FLOAT_REP := AAMP;
776 when others =>
777 FailN ("bad float rep field for");
778 end case;
779
780 N := N + 1;
781 Check_Spaces;
782
783 E.SIZE := Get_Nat;
784 Check_Spaces;
785
786 E.ALIGNMENT := Get_Nat;
787
788 if Buffer (N) /= ASCII.LF then
789 FailN ("junk at end of line for");
790 end if;
791
792 N := N + 1;
793 end;
794 end loop;
795 end Read_File;
796 end if;
797 end Set_Targ;