1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1996-2002 Free Software Foundation, Inc. --
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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
32 with Namet
; use Namet
;
34 with Osint
; use Osint
;
38 with Prj
.Ext
; use Prj
.Ext
;
40 with Prj
.Util
; use Prj
.Util
;
41 with Sdefault
; use Sdefault
;
42 with Snames
; use Snames
;
43 with Stringt
; use Stringt
;
45 with Types
; use Types
;
46 with Hostparm
; use Hostparm
;
47 -- Used to determine if we are in VMS or not for error message purposes
49 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
50 with Ada
.Command_Line
; use Ada
.Command_Line
;
51 with Ada
.Text_IO
; use Ada
.Text_IO
;
54 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
60 Ada_Include_Path
: constant String := "ADA_INCLUDE_PATH";
61 Ada_Objects_Path
: constant String := "ADA_OBJECTS_PATH";
63 Project_File
: String_Access
;
64 Project
: Prj
.Project_Id
;
65 Current_Verbosity
: Prj
.Verbosity
:= Prj
.Default
;
66 Tool_Package_Name
: Name_Id
:= No_Name
;
68 -- This flag indicates a switch -p (for gnatxref and gnatfind) for
69 -- an old fashioned project file. -p cannot be used in conjonction
72 Old_Project_File_Used
: Boolean := False;
74 -- A table to keep the switches on the command line
76 package Last_Switches
is new Table
.Table
77 (Table_Component_Type
=> String_Access
,
78 Table_Index_Type
=> Integer,
81 Table_Increment
=> 100,
82 Table_Name
=> "Gnatcmd.Last_Switches");
84 -- A table to keep the switches from the project file
86 package First_Switches
is new Table
.Table
87 (Table_Component_Type
=> String_Access
,
88 Table_Index_Type
=> Integer,
91 Table_Increment
=> 100,
92 Table_Name
=> "Gnatcmd.First_Switches");
98 -- The switch tables contain an entry for each switch recognized by the
99 -- command processor. The syntax of entries is as follows:
101 -- SWITCH_STRING ::= "/ command-qualifier-name TRANSLATION"
104 -- DIRECT_TRANSLATION
105 -- | DIRECTORIES_TRANSLATION
106 -- | FILE_TRANSLATION
107 -- | NO_SPACE_FILE_TRANSL
108 -- | NUMERIC_TRANSLATION
109 -- | STRING_TRANSLATION
110 -- | OPTIONS_TRANSLATION
111 -- | COMMANDS_TRANSLATION
112 -- | ALPHANUMPLUS_TRANSLATION
113 -- | OTHER_TRANSLATION
115 -- DIRECT_TRANSLATION ::= space UNIX_SWITCHES
116 -- DIRECTORIES_TRANSLATION ::= =* UNIX_SWITCH *
117 -- DIRECTORY_TRANSLATION ::= =% UNIX_SWITCH %
118 -- FILE_TRANSLATION ::= =@ UNIX_SWITCH @
119 -- NO_SPACE_FILE_TRANSL ::= =< UNIX_SWITCH >
120 -- NUMERIC_TRANSLATION ::= =# UNIX_SWITCH # | # number #
121 -- STRING_TRANSLATION ::= =" UNIX_SWITCH "
122 -- OPTIONS_TRANSLATION ::= =OPTION {space OPTION}
123 -- COMMANDS_TRANSLATION ::= =? ARGS space command-name
124 -- ALPHANUMPLUS_TRANSLATION ::= =| UNIX_SWITCH |
126 -- UNIX_SWITCHES ::= UNIX_SWITCH {, UNIX_SWITCH}
128 -- UNIX_SWITCH ::= unix-switch-string | !unix-switch-string | `string'
130 -- OPTION ::= option-name space UNIX_SWITCHES
132 -- ARGS ::= -cargs | -bargs | -largs
134 -- Here command-qual is the name of the switch recognized by the GNATCmd.
135 -- This is always given in upper case in the templates, although in the
136 -- actual commands, either upper or lower case is allowed.
138 -- The unix-switch-string always starts with a minus, and has no commas
139 -- or spaces in it. Case is significant in the unix switch string. If a
140 -- unix switch string is preceded by the not sign (!) it means that the
141 -- effect of the corresponding command qualifer is to remove any previous
142 -- occurrence of the given switch in the command line.
144 -- The DIRECTORIES_TRANSLATION format is used where a list of directories
145 -- is given. This possible corresponding formats recognized by GNATCmd are
146 -- as shown by the following example for the case of PATH
149 -- PATH=(direc,direc,direc,direc)
151 -- When more than one directory is present for the DIRECTORIES case, then
152 -- multiple instances of the corresponding unix switch are generated,
153 -- with the file name being substituted for the occurrence of *.
155 -- The FILE_TRANSLATION format is similar except that only a single
156 -- file is allowed, not a list of files, and only one unix switch is
157 -- generated as a result.
159 -- the NO_SPACE_FILE_TRANSL is similar to FILE_TRANSLATION, except that
160 -- no space is inserted between the switch and the file name.
162 -- The NUMERIC_TRANSLATION format is similar to the FILE_TRANSLATION case
163 -- except that the parameter is a decimal integer in the range 0 to 999.
165 -- For the OPTIONS_TRANSLATION case, GNATCmd similarly permits one or
166 -- more options to appear (although only in some cases does the use of
167 -- multiple options make logical sense). For example, taking the
168 -- case of ERRORS for GCC, the following are all allowed:
171 -- /ERRORS=(FULL,VERBOSE)
172 -- /ERRORS=(BRIEF IMMEDIATE)
174 -- If no option is provided (e.g. just /ERRORS is written), then the
175 -- first option in the list is the default option. For /ERRORS this
176 -- is NORMAL, so /ERRORS with no option is equivalent to /ERRORS=NORMAL.
178 -- The COMMANDS_TRANSLATION case is only used for gnatmake, to correspond
179 -- to the use of -cargs, -bargs and -largs (the ARGS string as indicated
180 -- is one of these three possibilities). The name given by COMMAND is the
181 -- corresponding command name to be used to interprete the switches to be
182 -- passed on. Switches of this type set modes, e.g. /COMPILER_QUALIFIERS
183 -- sets the mode so that all subsequent switches, up to another switch
184 -- with COMMANDS_TRANSLATION apply to the corresponding commands issued
185 -- by the make utility. For example
187 -- /COMPILER_QUALIFIERS /LIST /BINDER_QUALIFIERS /MAIN
188 -- /COMPILER_QUALIFIERS /NOLIST /COMPILE_CHECKS=SYNTAX
190 -- Clearly these switches must come at the end of the list of switches
191 -- since all subsequent switches apply to an issued command.
193 -- For the DIRECT_TRANSLATION case, an implicit additional entry is
194 -- created by prepending NO to the name of the qualifer, and then
195 -- inverting the sense of the UNIX_SWITCHES string. For example,
200 -- An implicit entry is created:
204 -- In the case where, a ! is already present, inverting the sense of the
205 -- switch means removing it.
208 -- A synonym to shorten the table
210 type String_Ptr
is access constant String;
211 -- String pointer type used throughout
213 type Switches
is array (Natural range <>) of String_Ptr
;
214 -- Type used for array of swtiches
216 type Switches_Ptr
is access constant Switches
;
218 --------------------------------
219 -- Switches for project files --
220 --------------------------------
222 S_Ext_Ref
: aliased constant S
:= "/EXTERNAL_REFERENCE=" & '"' &
225 S_Project_File
: aliased constant S
:= "/PROJECT_FILE=<" &
227 S_Project_Verb
: aliased constant S
:= "/PROJECT_FILE_VERBOSITY=" &
235 ----------------------------
236 -- Switches for GNAT BIND --
237 ----------------------------
239 S_Bind_Bind
: aliased constant S
:= "/BIND_FILE=" &
245 S_Bind_Build
: aliased constant S
:= "/BUILD_LIBRARY=|" &
248 S_Bind_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
251 S_Bind_Debug
: aliased constant S
:= "/DEBUG=" &
267 S_Bind_DebugX
: aliased constant S
:= "/NODEBUG " &
270 S_Bind_Elab
: aliased constant S
:= "/ELABORATION_DEPENDENCIES " &
273 S_Bind_Error
: aliased constant S
:= "/ERROR_LIMIT=#" &
276 S_Bind_Help
: aliased constant S
:= "/HELP " &
279 S_Bind_Init
: aliased constant S
:= "/INITIALIZE_SCALARS=" &
287 S_Bind_Library
: aliased constant S
:= "/LIBRARY_SEARCH=*" &
290 S_Bind_Linker
: aliased constant S
:= "/LINKER_OPTION_LIST " &
293 S_Bind_List
: aliased constant S
:= "/LIST_RESTRICTIONS " &
296 S_Bind_Main
: aliased constant S
:= "/MAIN " &
299 S_Bind_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
302 S_Bind_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
305 S_Bind_No_Time
: aliased constant S
:= "/NO_TIME_STAMP_CHECK " &
308 S_Bind_Object
: aliased constant S
:= "/OBJECT_LIST " &
311 S_Bind_Order
: aliased constant S
:= "/ORDER_OF_ELABORATION " &
314 S_Bind_Output
: aliased constant S
:= "/OUTPUT=@" &
317 S_Bind_OutputX
: aliased constant S
:= "/NOOUTPUT " &
320 S_Bind_Pess
: aliased constant S
:= "/PESSIMISTIC_ELABORATION " &
323 S_Bind_Read
: aliased constant S
:= "/READ_SOURCES=" &
331 S_Bind_ReadX
: aliased constant S
:= "/NOREAD_SOURCES " &
334 S_Bind_Rename
: aliased constant S
:= "/RENAME_MAIN=<" &
337 S_Bind_Report
: aliased constant S
:= "/REPORT_ERRORS=" &
345 S_Bind_ReportX
: aliased constant S
:= "/NOREPORT_ERRORS " &
348 S_Bind_Restr
: aliased constant S
:= "/RESTRICTION_LIST " &
351 S_Bind_RTS
: aliased constant S
:= "/RUNTIME_SYSTEM=|" &
354 S_Bind_Search
: aliased constant S
:= "/SEARCH=*" &
357 S_Bind_Shared
: aliased constant S
:= "/SHARED " &
360 S_Bind_Slice
: aliased constant S
:= "/TIME_SLICE=#" &
363 S_Bind_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
366 S_Bind_Time
: aliased constant S
:= "/TIME_STAMP_CHECK " &
369 S_Bind_Verbose
: aliased constant S
:= "/VERBOSE " &
372 S_Bind_Warn
: aliased constant S
:= "/WARNINGS=" &
380 S_Bind_WarnX
: aliased constant S
:= "/NOWARNINGS " &
383 Bind_Switches
: aliased constant Switches
:=
384 (S_Bind_Bind
'Access,
385 S_Bind_Build 'Access,
386 S_Bind_Current
'Access,
387 S_Bind_Debug 'Access,
388 S_Bind_DebugX
'Access,
390 S_Bind_Error
'Access,
394 S_Bind_Library
'Access,
395 S_Bind_Linker 'Access,
398 S_Bind_Nostinc
'Access,
399 S_Bind_Nostlib 'Access,
400 S_Bind_No_Time
'Access,
401 S_Bind_Object 'Access,
402 S_Bind_Order
'Access,
403 S_Bind_Output 'Access,
404 S_Bind_OutputX
'Access,
406 S_Project_File
'Access,
407 S_Project_Verb 'Access,
409 S_Bind_ReadX 'Access,
410 S_Bind_Rename
'Access,
411 S_Bind_Report 'Access,
412 S_Bind_ReportX
'Access,
413 S_Bind_Restr 'Access,
415 S_Bind_Search 'Access,
416 S_Bind_Shared
'Access,
417 S_Bind_Slice 'Access,
418 S_Bind_Source
'Access,
420 S_Bind_Verbose
'Access,
422 S_Bind_WarnX
'Access);
424 ----------------------------
425 -- Switches for GNAT CHOP --
426 ----------------------------
428 S_Chop_Comp : aliased constant S := "/COMPILATION " &
431 S_Chop_File : aliased constant S := "/FILE_NAME_MAX_LENGTH=#" &
434 S_Chop_Help : aliased constant S := "/HELP " &
437 S_Chop_Over : aliased constant S := "/OVERWRITE " &
440 S_Chop_Pres : aliased constant S := "/PRESERVE " &
443 S_Chop_Quiet : aliased constant S := "/QUIET " &
446 S_Chop_Ref : aliased constant S := "/REFERENCE " &
449 S_Chop_Verb : aliased constant S := "/VERBOSE " &
452 Chop_Switches : aliased constant Switches :=
453 (S_Chop_Comp 'Access,
458 S_Chop_Quiet
'Access,
460 S_Chop_Verb
'Access);
462 -------------------------------
463 -- Switches for GNAT COMPILE --
464 -------------------------------
466 S_GCC_Ada_83 : aliased constant S := "/83 " &
469 S_GCC_Ada_95 : aliased constant S := "/95 " &
472 S_GCC_Asm : aliased constant S := "/ASM " &
475 S_GCC_Checks : aliased constant S := "/CHECKS=" &
477 "-gnato,!-gnatE,!-gnatp " &
489 S_GCC_ChecksX : aliased constant S := "/NOCHECKS " &
490 "-gnatp,!-gnato,!-gnatE";
492 S_GCC_Compres : aliased constant S := "/COMPRESS_NAMES " &
495 S_GCC_Config : aliased constant S := "/CONFIGURATION_PRAGMAS_FILE=<" &
498 S_GCC_Current : aliased constant S := "/CURRENT_DIRECTORY " &
501 S_GCC_Debug : aliased constant S := "/DEBUG=" &
515 S_GCC_DebugX : aliased constant S := "/NODEBUG " &
518 S_GCC_Dist : aliased constant S := "/DISTRIBUTION_STUBS=" &
524 S_GCC_DistX : aliased constant S := "/NODISTRIBUTION_STUBS " &
527 S_GCC_Error : aliased constant S := "/ERROR_LIMIT=#" &
530 S_GCC_ErrorX : aliased constant S := "/NOERROR_LIMIT " &
533 S_GCC_Expand : aliased constant S := "/EXPAND_SOURCE " &
536 S_GCC_Extend : aliased constant S := "/EXTENSIONS_ALLOWED " &
539 S_GCC_File : aliased constant S := "/FILE_NAME_MAX_LENGTH=#" &
542 S_GCC_Force : aliased constant S := "/FORCE_ALI " &
545 S_GCC_Help : aliased constant S := "/HELP " &
548 S_GCC_Ident : aliased constant S := "/IDENTIFIER_CHARACTER_SET=" &
572 S_GCC_IdentX : aliased constant S := "/NOIDENTIFIER_CHARACTER_SET " &
575 S_GCC_Immed : aliased constant S := "/IMMEDIATE_ERRORS " &
578 S_GCC_Inline : aliased constant S := "/INLINE=" &
586 S_GCC_InlineX : aliased constant S := "/NOINLINE " &
589 S_GCC_Jumps : aliased constant S := "/LONGJMP_SETJMP " &
592 S_GCC_Length : aliased constant S := "/MAX_LINE_LENGTH=#" &
595 S_GCC_List : aliased constant S := "/LIST " &
598 S_GCC_Noadc : aliased constant S := "/NO_GNAT_ADC " &
601 S_GCC_Noload : aliased constant S := "/NOLOAD " &
604 S_GCC_Nostinc : aliased constant S := "/NOSTD_INCLUDES " &
607 S_GCC_Opt : aliased constant S := "/OPTIMIZE=" &
609 "-O2,!-O0,!-O1,!-O3 " &
611 "-O0,!-O1,!-O2,!-O3 " &
613 "-O1,!-O0,!-O2,!-O3 " &
615 "-O1,!-O0,!-O2,!-O3 " &
619 "-O3,!-O0,!-O1,!-O2";
621 S_GCC_OptX : aliased constant S := "/NOOPTIMIZE " &
622 "-O0,!-O1,!-O2,!-O3";
624 S_GCC_Polling : aliased constant S := "/POLLING " &
627 S_GCC_Report : aliased constant S := "/REPORT_ERRORS=" &
639 S_GCC_ReportX : aliased constant S := "/NOREPORT_ERRORS " &
642 S_GCC_Repinfo : aliased constant S := "/REPRESENTATION_INFO=" &
654 S_GCC_RepinfX : aliased constant S := "/NOREPRESENTATION_INFO " &
657 S_GCC_Search : aliased constant S := "/SEARCH=*" &
660 S_GCC_Style : aliased constant S := "/STYLE_CHECKS=" &
705 "ORDERED_SUBPROGRAMS " &
711 "RM_COLUMN_LAYOUT " &
718 S_GCC_StyleX : aliased constant S := "/NOSTYLE_CHECKS " &
721 S_GCC_Syntax : aliased constant S := "/SYNTAX_ONLY " &
724 S_GCC_Trace : aliased constant S := "/TRACE_UNITS " &
727 S_GCC_Tree : aliased constant S := "/TREE_OUTPUT " &
730 S_GCC_Trys : aliased constant S := "/TRY_SEMANTICS " &
733 S_GCC_Units : aliased constant S := "/UNITS_LIST " &
736 S_GCC_Unique : aliased constant S := "/UNIQUE_ERROR_TAG " &
739 S_GCC_Upcase : aliased constant S := "/UPPERCASE_EXTERNALS " &
742 S_GCC_Valid : aliased constant S := "/VALIDITY_CHECKING=" &
784 S_GCC_Verbose : aliased constant S := "/VERBOSE " &
787 S_GCC_Warn : aliased constant S := "/WARNINGS=" &
789 "!-gnatws,!-gnatwe " &
794 "NOBIASED_ROUNDING " &
800 "IMPLICIT_DEREFERENCE " &
802 "NO_IMPLICIT_DEREFERENCE " &
816 "NOIMPLEMENTATION " &
818 "INEFFECTIVE_INLINE " &
820 "NOINEFFECTIVE_INLINE " &
838 "UNREFERENCED_FORMALS " &
840 "NOUNREFERENCED_FORMALS " &
847 S_GCC_WarnX : aliased constant S := "/NOWARNINGS " &
850 S_GCC_Wide : aliased constant S := "/WIDE_CHARACTER_ENCODING=" &
866 S_GCC_WideX : aliased constant S := "/NOWIDE_CHARACTER_ENCODING " &
869 S_GCC_Xdebug : aliased constant S := "/XDEBUG " &
872 S_GCC_Xref : aliased constant S := "/XREF=" &
878 GCC_Switches : aliased constant Switches :=
879 (S_GCC_Ada_83 'Access,
880 S_GCC_Ada_95
'Access,
882 S_GCC_Checks
'Access,
883 S_GCC_ChecksX 'Access,
884 S_GCC_Compres
'Access,
885 S_GCC_Config 'Access,
886 S_GCC_Current
'Access,
888 S_GCC_DebugX
'Access,
892 S_GCC_ErrorX
'Access,
893 S_GCC_Expand 'Access,
894 S_GCC_Extend
'Access,
900 S_GCC_IdentX
'Access,
902 S_GCC_Inline
'Access,
903 S_GCC_InlineX 'Access,
905 S_GCC_Length 'Access,
908 S_GCC_Noload
'Access,
909 S_GCC_Nostinc 'Access,
912 S_GCC_Polling
'Access,
913 S_Project_File'Access,
914 S_Project_Verb'Access,
915 S_GCC_Report 'Access,
916 S_GCC_ReportX
'Access,
917 S_GCC_Repinfo 'Access,
918 S_GCC_RepinfX
'Access,
919 S_GCC_Search 'Access,
921 S_GCC_StyleX 'Access,
922 S_GCC_Syntax
'Access,
927 S_GCC_Unique 'Access,
928 S_GCC_Upcase
'Access,
930 S_GCC_Verbose
'Access,
935 S_GCC_Xdebug 'Access,
938 ----------------------------
939 -- Switches for GNAT ELIM --
940 ----------------------------
942 S_Elim_All : aliased constant S := "/ALL " &
945 S_Elim_Bind : aliased constant S := "/BIND_FILE=<" &
948 S_Elim_Miss : aliased constant S := "/MISSED " &
951 S_Elim_Quiet : aliased constant S := "/QUIET " &
954 S_Elim_Tree : aliased constant S := "/TREE_DIRS=*" &
957 S_Elim_Verb : aliased constant S := "/VERBOSE " &
960 Elim_Switches : aliased constant Switches :=
964 S_Elim_Quiet
'Access,
966 S_Elim_Verb
'Access);
968 ----------------------------
969 -- Switches for GNAT FIND --
970 ----------------------------
972 S_Find_All : aliased constant S := "/ALL_FILES " &
975 S_Find_Deriv : aliased constant S := "/DERIVED_TYPE_INFORMATION " &
978 S_Find_Expr : aliased constant S := "/EXPRESSIONS " &
981 S_Find_Full : aliased constant S := "/FULL_PATHNAME " &
984 S_Find_Ignore : aliased constant S := "/IGNORE_LOCALS " &
987 S_Find_Nostinc : aliased constant S := "/NOSTD_INCLUDES " &
990 S_Find_Nostlib : aliased constant S := "/NOSTD_LIBRARIES " &
993 S_Find_Object : aliased constant S := "/OBJECT_SEARCH=*" &
996 S_Find_Print : aliased constant S := "/PRINT_LINES " &
999 S_Find_Project : aliased constant S := "/PROJECT=@" &
1002 S_Find_Ref : aliased constant S := "/REFERENCES " &
1005 S_Find_Search : aliased constant S := "/SEARCH=*" &
1008 S_Find_Source : aliased constant S := "/SOURCE_SEARCH=*" &
1011 S_Find_Types : aliased constant S := "/TYPE_HIERARCHY " &
1014 Find_Switches : aliased constant Switches :=
1015 (S_Find_All 'Access,
1016 S_Find_Deriv
'Access,
1017 S_Find_Expr 'Access,
1019 S_Find_Full 'Access,
1020 S_Find_Ignore
'Access,
1021 S_Find_Nostinc 'Access,
1022 S_Find_Nostlib
'Access,
1023 S_Find_Object 'Access,
1024 S_Find_Print
'Access,
1025 S_Find_Project 'Access,
1026 S_Project_File
'Access,
1027 S_Project_Verb 'Access,
1029 S_Find_Search 'Access,
1030 S_Find_Source
'Access,
1031 S_Find_Types 'Access);
1033 ------------------------------
1034 -- Switches for GNAT KRUNCH --
1035 ------------------------------
1037 S_Krunch_Count
: aliased constant S
:= "/COUNT=#" &
1040 Krunch_Switches
: aliased constant Switches
:=
1041 (1 .. 1 => S_Krunch_Count
'Access);
1043 -------------------------------
1044 -- Switches for GNAT LIBRARY --
1045 -------------------------------
1047 S_Lbr_Config : aliased constant S := "/CONFIG=@" &
1050 S_Lbr_Create : aliased constant S := "/CREATE=%" &
1053 S_Lbr_Delete : aliased constant S := "/DELETE=%" &
1056 S_Lbr_Set : aliased constant S := "/SET=%" &
1059 Lbr_Switches : aliased constant Switches :=
1060 (S_Lbr_Config 'Access,
1061 S_Lbr_Create
'Access,
1062 S_Lbr_Delete 'Access,
1065 ----------------------------
1066 -- Switches for GNAT LINK --
1067 ----------------------------
1069 S_Link_Bind : aliased constant S := "/BIND_FILE=" &
1075 S_Link_Debug : aliased constant S := "/DEBUG=" &
1085 S_Link_Execut : aliased constant S := "/EXECUTABLE=@" &
1088 S_Link_Force : aliased constant S := "/FORCE_OBJECT_FILE_LIST " &
1091 S_Link_Ident : aliased constant S := "/IDENTIFICATION=" & '"' &
1092 "--for-linker=IDENT=" &
1095 S_Link_Nocomp
: aliased constant S
:= "/NOCOMPILE " &
1098 S_Link_Nofiles
: aliased constant S
:= "/NOSTART_FILES " &
1101 S_Link_Noinhib
: aliased constant S
:= "/NOINHIBIT-EXEC " &
1102 "--for-linker=--noinhibit-exec";
1104 S_Link_Static
: aliased constant S
:= "/STATIC " &
1105 "--for-linker=-static";
1107 S_Link_Verb
: aliased constant S
:= "/VERBOSE " &
1110 S_Link_ZZZZZ
: aliased constant S
:= "/<other> " &
1113 Link_Switches
: aliased constant Switches
:=
1114 (S_Link_Bind
'Access,
1115 S_Link_Debug 'Access,
1116 S_Link_Execut
'Access,
1118 S_Link_Force
'Access,
1119 S_Link_Ident 'Access,
1120 S_Link_Nocomp
'Access,
1121 S_Link_Nofiles 'Access,
1122 S_Link_Noinhib
'Access,
1123 S_Project_File 'Access,
1124 S_Project_Verb
'Access,
1125 S_Link_Static 'Access,
1126 S_Link_Verb
'Access,
1127 S_Link_ZZZZZ 'Access);
1129 ----------------------------
1130 -- Switches for GNAT LIST --
1131 ----------------------------
1133 S_List_All
: aliased constant S
:= "/ALL_UNITS " &
1136 S_List_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
1139 S_List_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1142 S_List_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1145 S_List_Output
: aliased constant S
:= "/OUTPUT=" &
1159 S_List_Search
: aliased constant S
:= "/SEARCH=*" &
1162 S_List_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1165 List_Switches
: aliased constant Switches
:=
1166 (S_List_All
'Access,
1167 S_List_Current 'Access,
1169 S_List_Nostinc 'Access,
1170 S_List_Object
'Access,
1171 S_List_Output 'Access,
1172 S_Project_File
'Access,
1173 S_Project_Verb 'Access,
1174 S_List_Search
'Access,
1175 S_List_Source 'Access);
1177 ----------------------------
1178 -- Switches for GNAT MAKE --
1179 ----------------------------
1181 S_Make_Actions
: aliased constant S
:= "/ACTIONS=" &
1189 S_Make_All
: aliased constant S
:= "/ALL_FILES " &
1192 S_Make_Bind
: aliased constant S
:= "/BINDER_QUALIFIERS=?" &
1195 S_Make_Comp
: aliased constant S
:= "/COMPILER_QUALIFIERS=?" &
1198 S_Make_Cond
: aliased constant S
:= "/CONDITIONAL_SOURCE_SEARCH=*" &
1201 S_Make_Cont
: aliased constant S
:= "/CONTINUE_ON_ERROR " &
1204 S_Make_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
1207 S_Make_Dep
: aliased constant S
:= "/DEPENDENCIES_LIST " &
1210 S_Make_Doobj
: aliased constant S
:= "/DO_OBJECT_CHECK " &
1213 S_Make_Execut
: aliased constant S
:= "/EXECUTABLE=@" &
1216 S_Make_Force
: aliased constant S
:= "/FORCE_COMPILE " &
1219 S_Make_Inplace
: aliased constant S
:= "/IN_PLACE " &
1222 S_Make_Library
: aliased constant S
:= "/LIBRARY_SEARCH=*" &
1225 S_Make_Link
: aliased constant S
:= "/LINKER_QUALIFIERS=?" &
1228 S_Make_Mapping
: aliased constant S
:= "/MAPPING " &
1231 S_Make_Minimal
: aliased constant S
:= "/MINIMAL_RECOMPILATION " &
1234 S_Make_Nolink
: aliased constant S
:= "/NOLINK " &
1237 S_Make_Nomain
: aliased constant S
:= "/NOMAIN " &
1240 S_Make_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1243 S_Make_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
1246 S_Make_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1249 S_Make_Proc
: aliased constant S
:= "/PROCESSES=#" &
1252 S_Make_Nojobs
: aliased constant S
:= "/NOPROCESSES " &
1255 S_Make_Quiet
: aliased constant S
:= "/QUIET " &
1258 S_Make_Reason
: aliased constant S
:= "/REASONS " &
1261 S_Make_RTS
: aliased constant S
:= "/RUNTIME_SYSTEM=|" &
1264 S_Make_Search
: aliased constant S
:= "/SEARCH=*" &
1267 S_Make_Skip
: aliased constant S
:= "/SKIP_MISSING=*" &
1270 S_Make_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1273 S_Make_Switch
: aliased constant S
:= "/SWITCH_CHECK " &
1276 S_Make_Unique
: aliased constant S
:= "/UNIQUE " &
1279 S_Make_Verbose
: aliased constant S
:= "/VERBOSE " &
1282 Make_Switches
: aliased constant Switches
:=
1283 (S_Make_Actions
'Access,
1285 S_Make_Bind
'Access,
1286 S_Make_Comp 'Access,
1287 S_Make_Cond
'Access,
1288 S_Make_Cont 'Access,
1289 S_Make_Current
'Access,
1291 S_Make_Doobj
'Access,
1292 S_Make_Execut 'Access,
1294 S_Make_Force 'Access,
1295 S_Make_Inplace
'Access,
1296 S_Make_Library 'Access,
1297 S_Make_Link
'Access,
1298 S_Make_Mapping 'Access,
1299 S_Make_Minimal
'Access,
1300 S_Make_Nolink 'Access,
1301 S_Make_Nomain
'Access,
1302 S_Make_Nostinc 'Access,
1303 S_Make_Nostlib
'Access,
1304 S_Make_Object 'Access,
1305 S_Make_Proc
'Access,
1306 S_Project_File 'Access,
1307 S_Project_Verb
'Access,
1308 S_Make_Nojobs 'Access,
1309 S_Make_Quiet
'Access,
1310 S_Make_Reason 'Access,
1312 S_Make_Search 'Access,
1313 S_Make_Skip
'Access,
1314 S_Make_Source 'Access,
1315 S_Make_Switch
'Access,
1316 S_Make_Unique 'Access,
1317 S_Make_Verbose
'Access);
1319 ----------------------------
1320 -- Switches for GNAT Name --
1321 ----------------------------
1323 S_Name_Conf : aliased constant S := "/CONFIG_FILE=<" &
1326 S_Name_Dirs : aliased constant S := "/SOURCE_DIRS=*" &
1329 S_Name_Dfile : aliased constant S := "/DIRS_FILE=<" &
1332 S_Name_Help : aliased constant S := "/HELP" &
1335 S_Name_Proj : aliased constant S := "/PROJECT_FILE=<" &
1338 S_Name_Verbose : aliased constant S := "/VERBOSE" &
1341 Name_Switches : aliased constant Switches :=
1342 (S_Name_Conf 'Access,
1343 S_Name_Dirs
'Access,
1344 S_Name_Dfile 'Access,
1345 S_Name_Help
'Access,
1346 S_Name_Proj 'Access,
1347 S_Name_Verbose
'Access);
1349 ----------------------------------
1350 -- Switches for GNAT PREPROCESS --
1351 ----------------------------------
1353 S_Prep_Assoc : aliased constant S := "/ASSOCIATE=" & '"' &
1356 S_Prep_Blank : aliased constant S := "/BLANK_LINES " &
1359 S_Prep_Com : aliased constant S := "/COMMENTS " &
1362 S_Prep_Ref : aliased constant S := "/REFERENCE " &
1365 S_Prep_Remove : aliased constant S := "/REMOVE " &
1368 S_Prep_Symbols : aliased constant S := "/SYMBOLS " &
1371 S_Prep_Undef : aliased constant S := "/UNDEFINED " &
1374 Prep_Switches : aliased constant Switches :=
1375 (S_Prep_Assoc 'Access,
1376 S_Prep_Blank
'Access,
1379 S_Prep_Remove 'Access,
1380 S_Prep_Symbols
'Access,
1381 S_Prep_Undef 'Access);
1383 ------------------------------
1384 -- Switches for GNAT SHARED --
1385 ------------------------------
1387 S_Shared_Debug
: aliased constant S
:= "/DEBUG=" &
1397 S_Shared_Image
: aliased constant S
:= "/IMAGE=@" &
1400 S_Shared_Ident
: aliased constant S
:= "/IDENTIFICATION=" & '"' &
1401 "--for-linker=IDENT=" &
1404 S_Shared_Nofiles
: aliased constant S
:= "/NOSTART_FILES " &
1407 S_Shared_Noinhib
: aliased constant S
:= "/NOINHIBIT-IMAGE " &
1408 "--for-linker=--noinhibit-exec";
1410 S_Shared_Verb
: aliased constant S
:= "/VERBOSE " &
1413 S_Shared_ZZZZZ
: aliased constant S
:= "/<other> " &
1416 Shared_Switches
: aliased constant Switches
:=
1417 (S_Shared_Debug
'Access,
1418 S_Shared_Image 'Access,
1419 S_Shared_Ident
'Access,
1420 S_Shared_Nofiles 'Access,
1421 S_Shared_Noinhib
'Access,
1422 S_Shared_Verb 'Access,
1423 S_Shared_ZZZZZ
'Access);
1425 --------------------------------
1426 -- Switches for GNAT STANDARD --
1427 --------------------------------
1429 Standard_Switches : aliased constant Switches := (1 .. 0 => null);
1431 ----------------------------
1432 -- Switches for GNAT STUB --
1433 ----------------------------
1435 S_Stub_Current : aliased constant S := "/CURRENT_DIRECTORY " &
1438 S_Stub_Full : aliased constant S := "/FULL " &
1441 S_Stub_Header : aliased constant S := "/HEADER=" &
1447 S_Stub_Indent : aliased constant S := "/INDENTATION=#" &
1450 S_Stub_Length : aliased constant S := "/LINE_LENGTH=#" &
1453 S_Stub_Quiet : aliased constant S := "/QUIET " &
1456 S_Stub_Search : aliased constant S := "/SEARCH=*" &
1459 S_Stub_Tree : aliased constant S := "/TREE_FILE=" &
1467 S_Stub_Verbose : aliased constant S := "/VERBOSE " &
1470 Stub_Switches : aliased constant Switches :=
1471 (S_Stub_Current 'Access,
1472 S_Stub_Full
'Access,
1473 S_Stub_Header 'Access,
1474 S_Stub_Indent
'Access,
1475 S_Stub_Length 'Access,
1476 S_Stub_Quiet
'Access,
1477 S_Stub_Search 'Access,
1478 S_Stub_Tree
'Access,
1479 S_Stub_Verbose 'Access);
1481 ----------------------------
1482 -- Switches for GNAT XREF --
1483 ----------------------------
1485 S_Xref_All
: aliased constant S
:= "/ALL_FILES " &
1488 S_Xref_Deriv
: aliased constant S
:= "/DERIVED_TYPES " &
1491 S_Xref_Full
: aliased constant S
:= "/FULL_PATHNAME " &
1494 S_Xref_Global
: aliased constant S
:= "/IGNORE_LOCALS " &
1497 S_Xref_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1500 S_Xref_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
1503 S_Xref_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1506 S_Xref_Project
: aliased constant S
:= "/PROJECT=@" &
1509 S_Xref_Search
: aliased constant S
:= "/SEARCH=*" &
1512 S_Xref_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1515 S_Xref_Output
: aliased constant S
:= "/UNUSED " &
1518 S_Xref_Tags
: aliased constant S
:= "/TAGS " &
1521 Xref_Switches
: aliased constant Switches
:=
1522 (S_Xref_All
'Access,
1523 S_Xref_Deriv 'Access,
1525 S_Xref_Full 'Access,
1526 S_Xref_Global
'Access,
1527 S_Xref_Nostinc 'Access,
1528 S_Xref_Nostlib
'Access,
1529 S_Xref_Object 'Access,
1530 S_Xref_Project
'Access,
1531 S_Project_File 'Access,
1532 S_Project_Verb
'Access,
1533 S_Xref_Search 'Access,
1534 S_Xref_Source
'Access,
1535 S_Xref_Output 'Access,
1536 S_Xref_Tags
'Access);
1542 -- The command table contains an entry for each command recognized by
1543 -- GNATCmd. The entries are represented by an array of records.
1545 type Parameter_Type is
1546 -- A parameter is defined as a whitespace bounded string, not begining
1547 -- with a slash. (But see note under FILES_OR_WILDCARD).
1549 -- A required file or directory parameter.
1552 -- An optional file or directory parameter.
1555 -- A parameter that's passed through as is (not canonicalized)
1558 -- An unlimited number of whitespace separate file or directory
1559 -- parameters including wildcard specifications.
1562 -- Un unlimited number of whitespace separated paameters that are
1563 -- passed through as is (not canonicalized).
1566 -- A comma separated list of files and/or wildcard file specifications.
1567 -- A comma preceded by or followed by whitespace is considered as a
1568 -- single comma character w/o whitespace.
1570 type Parameter_Array is array (Natural range <>) of Parameter_Type;
1571 type Parameter_Ref is access all Parameter_Array;
1573 type Command_Type is
1574 (Bind, Chop, Compile, Elim, Find, Krunch, Library, Link, List,
1575 Make, Name, Preprocess, Shared, Standard, Stub, Xref, Undefined);
1577 type Alternate_Command is (Comp, Ls, Kr, Prep, Psta);
1578 -- Alternate command libel for non VMS system
1580 Corresponding_To : constant array (Alternate_Command) of Command_Type :=
1586 -- Mapping of alternate commands to commands
1588 subtype Real_Command_Type is Command_Type range Bind .. Xref;
1590 type Command_Entry is record
1592 -- Command name for GNAT xxx command
1595 -- A usage string, used for error messages
1597 Unixcmd : String_Ptr;
1598 -- Corresponding Unix command
1600 Unixsws : Argument_List_Access;
1601 -- Switches for the Unix command
1604 -- When True, the command can only be used on VMS
1606 Switches : Switches_Ptr;
1607 -- Pointer to array of switch strings
1609 Params : Parameter_Ref;
1610 -- Describes the allowable types of parameters.
1611 -- Params (1) is the type of the first parameter, etc.
1612 -- An empty parameter array means this command takes no parameters.
1614 Defext : String (1 .. 3);
1615 -- Default extension. If non-blank, then this extension is supplied by
1616 -- default as the extension for any file parameter which does not have
1617 -- an extension already.
1620 -------------------------
1621 -- INTERNAL STRUCTURES --
1622 -------------------------
1624 -- The switches and commands are defined by strings in the previous
1625 -- section so that they are easy to modify, but internally, they are
1626 -- kept in a more conveniently accessible form described in this
1629 -- Commands, command qualifers and options have a similar common format
1630 -- so that searching for matching names can be done in a common manner.
1632 type Item_Id is (Id_Command, Id_Switch, Id_Option);
1634 type Translation_Type is
1637 -- A qualifier with no options.
1638 -- Example: GNAT MAKE /VERBOSE
1641 -- A qualifier followed by a list of directories
1642 -- Example: GNAT COMPILE /SEARCH=([], [.FOO], [.BAR])
1645 -- A qualifier followed by one directory
1646 -- Example: GNAT LIBRARY /SET=[.VAXFLOATLIB]
1649 -- A qualifier followed by a filename
1650 -- Example: GNAT LINK /EXECUTABLE=FOO.EXE
1653 -- A qualifier followed by a filename
1654 -- Example: GNAT MAKE /PROJECT_FILE=PRJ.GPR
1657 -- A qualifier followed by a numeric value.
1658 -- Example: GNAT CHOP /FILE_NAME_MAX_LENGTH=39
1661 -- A qualifier followed by a quoted string. Only used by
1662 -- /IDENTIFICATION qualfier.
1663 -- Example: GNAT LINK /IDENTIFICATION="3.14a1 version"
1666 -- A qualifier followed by a list of options.
1667 -- Example: GNAT COMPILE /REPRESENTATION_INFO=(ARRAYS,OBJECTS)
1670 -- A qualifier followed by a list. Only used for
1671 -- MAKE /COMPILER_QUALIFIERS /BINDER_QUALIFIERS /LINKER_QUALIFIERS
1672 -- (gnatmake -cargs -bargs -largs )
1673 -- Example: GNAT MAKE ... /LINKER_QUALIFIERS /VERBOSE FOOBAR.OBJ
1676 -- A qualifier passed directly to the linker. Only used
1677 -- for LINK and SHARED if no other match is found.
1678 -- Example: GNAT LINK FOO.ALI /SYSSHR
1681 -- A qualifier followed by a legal linker symbol prefix. Only used
1682 -- for BIND /BUILD_LIBRARY (gnatbind -Lxyz).
1683 -- Example: GNAT BIND /BUILD_LIBRARY=foobar
1686 type Item (Id : Item_Id);
1687 type Item_Ptr is access all Item;
1689 type Item (Id : Item_Id) is record
1691 -- Name of the command, switch (with slash) or option
1694 -- Pointer to next item on list, always has the same Id value
1696 Command : Command_Type := Undefined;
1698 Unix_String : String_Ptr := null;
1699 -- Corresponding Unix string. For a command, this is the unix command
1700 -- name and possible default switches. For a switch or option it is
1701 -- the unix switch string.
1707 Switches : Item_Ptr;
1708 -- Pointer to list of switch items for the command, linked
1709 -- through the Next fields with null terminating the list.
1712 -- Usage information, used only for errors and the default
1713 -- list of commands output.
1715 Params : Parameter_Ref;
1716 -- Array of parameters
1718 Defext : String (1 .. 3);
1719 -- Default extension. If non-blank, then this extension is
1720 -- supplied by default as the extension for any file parameter
1721 -- which does not have an extension already.
1725 Translation : Translation_Type;
1726 -- Type of switch translation. For all cases, except Options,
1727 -- this is the only field needed, since the Unix translation
1728 -- is found in Unix_String.
1731 -- For the Options case, this field is set to point to a list
1732 -- of options item (for this case Unix_String is null in the
1733 -- main switch item). The end of the list is marked by null.
1738 -- No special fields needed, since Name and Unix_String are
1739 -- sufficient to completely described an option.
1744 subtype Command_Item is Item (Id_Command);
1745 subtype Switch_Item is Item (Id_Switch);
1746 subtype Option_Item is Item (Id_Option);
1748 ----------------------------------
1749 -- Declarations for GNATCMD use --
1750 ----------------------------------
1752 Commands : Item_Ptr;
1753 -- Pointer to head of list of command items, one for each command, with
1754 -- the end of the list marked by a null pointer.
1756 Last_Command : Item_Ptr;
1757 -- Pointer to last item in Commands list
1759 Normal_Exit : exception;
1760 -- Raise this exception for normal program termination
1762 Error_Exit : exception;
1763 -- Raise this exception if error detected
1765 Errors : Natural := 0;
1766 -- Count errors detected
1768 Command_Arg : Positive := 1;
1771 -- Pointer to command item for current command
1773 Make_Commands_Active : Item_Ptr := null;
1774 -- Set to point to Command entry for COMPILE, BIND, or LINK as appropriate
1775 -- if a COMMANDS_TRANSLATION switch has been encountered while processing
1778 My_Exit_Status : Exit_Status := Success;
1780 package Buffer is new Table.Table
1781 (Table_Component_Type => Character,
1782 Table_Index_Type => Integer,
1783 Table_Low_Bound => 1,
1784 Table_Initial => 4096,
1785 Table_Increment => 2,
1786 Table_Name => "Buffer");
1788 Param_Count : Natural := 0;
1789 -- Number of parameter arguments so far
1794 Display_Command : Boolean := False;
1795 -- Set true if /? switch causes display of generated command (on VMS)
1797 The_Command : Command_Type;
1800 -----------------------
1801 -- Local Subprograms --
1802 -----------------------
1804 function Index (Char : Character; Str : String) return Natural;
1805 -- Returns the first occurrence of Char in Str.
1806 -- Returns 0 if Char is not in Str.
1808 function Init_Object_Dirs return Argument_List;
1810 function Invert_Sense (S : String) return String_Ptr;
1811 -- Given a unix switch string S, computes the inverse (adding or
1812 -- removing ! characters as required), and returns a pointer to
1813 -- the allocated result on the heap.
1815 function Is_Extensionless (F : String) return Boolean;
1816 -- Returns true if the filename has no extension.
1818 function Match (S1, S2 : String) return Boolean;
1819 -- Determines whether S1 and S2 match. This is a case insensitive match.
1821 function Match_Prefix (S1, S2 : String) return Boolean;
1822 -- Determines whether S1 matches a prefix of S2. This is also a case
1823 -- insensitive match (for example Match ("AB","abc") is True).
1825 function Matching_Name
1828 Quiet : Boolean := False)
1830 -- Determines if the item list headed by Itm and threaded through the
1831 -- Next fields (with null marking the end of the list), contains an
1832 -- entry that uniquely matches the given string. The match is case
1833 -- insensitive and permits unique abbreviation. If the match succeeds,
1834 -- then a pointer to the matching item is returned. Otherwise, an
1835 -- appropriate error message is written. Note that the discriminant
1836 -- of Itm is used to determine the appropriate form of this message.
1837 -- Quiet is normally False as shown, if it is set to True, then no
1838 -- error message is generated in a not found situation (null is still
1839 -- returned to indicate the not-found situation).
1841 procedure Non_VMS_Usage;
1842 -- Display usage for platforms other than VMS
1844 function OK_Alphanumerplus (S : String) return Boolean;
1845 -- Checks that S is a string of alphanumeric characters,
1846 -- returning True if all alphanumeric characters,
1847 -- False if empty or a non-alphanumeric character is present.
1849 function OK_Integer (S : String) return Boolean;
1850 -- Checks that S is a string of digits, returning True if all digits,
1851 -- False if empty or a non-digit is present.
1853 procedure Output_Version;
1854 -- Output the version of this program
1856 procedure Place (C : Character);
1857 -- Place a single character in the buffer, updating Ptr
1859 procedure Place (S : String);
1860 -- Place a string character in the buffer, updating Ptr
1862 procedure Place_Lower (S : String);
1863 -- Place string in buffer, forcing letters to lower case, updating Ptr
1865 procedure Place_Unix_Switches (S : String_Ptr);
1866 -- Given a unix switch string, place corresponding switches in Buffer,
1867 -- updating Ptr appropriatelly. Note that in the case of use of ! the
1868 -- result may be to remove a previously placed switch.
1870 procedure Set_Library_For
1871 (Project : Project_Id;
1872 There_Are_Libraries : in out Boolean);
1873 -- If Project is a library project, add the correct
1874 -- -L and -l switches to the linker invocation.
1876 procedure Set_Libraries is
1877 new For_Every_Project_Imported (Boolean, Set_Library_For);
1878 -- Add the -L and -l switches to the linker for all
1879 -- of the library projects.
1881 procedure Validate_Command_Or_Option (N : String_Ptr);
1882 -- Check that N is a valid command or option name, i.e. that it is of the
1883 -- form of an Ada identifier with upper case letters and underscores.
1885 procedure Validate_Unix_Switch (S : String_Ptr);
1886 -- Check that S is a valid switch string as described in the syntax for
1887 -- the switch table item UNIX_SWITCH or else begins with a backquote.
1889 procedure VMS_Conversion (The_Command : out Command_Type);
1890 -- Converts VMS command line to equivalent Unix command line
1896 function Index (Char : Character; Str : String) return Natural is
1898 for Index in Str'Range loop
1899 if Str (Index) = Char then
1907 ----------------------
1908 -- Init_Object_Dirs --
1909 ----------------------
1911 function Init_Object_Dirs return Argument_List is
1912 Object_Dirs : Integer;
1913 Object_Dir : Argument_List (1 .. 256);
1914 Object_Dir_Name : String_Access;
1918 Object_Dir_Name := String_Access (Object_Dir_Default_Name);
1919 Get_Next_Dir_In_Path_Init (Object_Dir_Name);
1923 Dir : String_Access := String_Access
1924 (Get_Next_Dir_In_Path (Object_Dir_Name));
1926 exit when Dir = null;
1927 Object_Dirs := Object_Dirs + 1;
1928 Object_Dir (Object_Dirs) :=
1930 To_Canonical_Dir_Spec
1932 (Normalize_Directory_Name
(Dir
.all).all,
1933 True).all, True).all);
1937 Object_Dirs
:= Object_Dirs
+ 1;
1938 Object_Dir
(Object_Dirs
) := new String'("-lgnat");
1940 if Hostparm.OpenVMS then
1941 Object_Dirs := Object_Dirs + 1;
1942 Object_Dir (Object_Dirs) := new String'("-ldecgnat");
1945 return Object_Dir
(1 .. Object_Dirs
);
1946 end Init_Object_Dirs
;
1952 function Invert_Sense
(S
: String) return String_Ptr
is
1953 Sinv
: String (1 .. S
'Length * 2);
1954 -- Result (for sure long enough)
1956 Sinvp
: Natural := 0;
1957 -- Pointer to output string
1960 for Sp
in S
'Range loop
1961 if Sp
= S
'First or else S
(Sp
- 1) = ',' then
1962 if S
(Sp
) = '!' then
1965 Sinv
(Sinvp
+ 1) := '!';
1966 Sinv
(Sinvp
+ 2) := S
(Sp
);
1971 Sinv
(Sinvp
+ 1) := S
(Sp
);
1976 return new String'(Sinv (1 .. Sinvp));
1979 ----------------------
1980 -- Is_Extensionless --
1981 ----------------------
1983 function Is_Extensionless (F : String) return Boolean is
1985 for J in reverse F'Range loop
1988 elsif F (J) = '/' or else F (J) = ']' or else F (J) = ':' then
1994 end Is_Extensionless;
2000 function Match (S1, S2 : String) return Boolean is
2001 Dif : constant Integer := S2'First - S1'First;
2005 if S1'Length /= S2'Length then
2009 for J in S1'Range loop
2010 if To_Lower (S1 (J)) /= To_Lower (S2 (J + Dif)) then
2023 function Match_Prefix (S1, S2 : String) return Boolean is
2025 if S1'Length > S2'Length then
2028 return Match (S1, S2 (S2'First .. S2'First + S1'Length - 1));
2036 function Matching_Name
2039 Quiet : Boolean := False)
2045 -- Little procedure to output command/qualifier/option as appropriate
2046 -- and bump error count.
2058 Errors := Errors + 1;
2063 Put (Standard_Error, "command");
2067 Put (Standard_Error, "qualifier");
2069 Put (Standard_Error, "switch");
2073 Put (Standard_Error, "option");
2077 Put (Standard_Error, "input");
2081 Put (Standard_Error, ": ");
2082 Put (Standard_Error, S);
2085 -- Start of processing for Matching_Name
2088 -- If exact match, that's the one we want
2091 while P1 /= null loop
2092 if Match (S, P1.Name.all) then
2099 -- Now check for prefix matches
2102 while P1 /= null loop
2103 if P1.Name.all = "/<other>" then
2106 elsif not Match_Prefix (S, P1.Name.all) then
2110 -- Here we have found one matching prefix, so see if there is
2111 -- another one (which is an ambiguity)
2114 while P2 /= null loop
2115 if Match_Prefix (S, P2.Name.all) then
2117 Put (Standard_Error, "ambiguous ");
2119 Put (Standard_Error, " (matches ");
2120 Put (Standard_Error, P1.Name.all);
2122 while P2 /= null loop
2123 if Match_Prefix (S, P2.Name.all) then
2124 Put (Standard_Error, ',');
2125 Put (Standard_Error, P2.Name.all);
2131 Put_Line (Standard_Error, ")");
2140 -- If we fall through that loop, then there was only one match
2146 -- If we fall through outer loop, there was no match
2149 Put (Standard_Error, "unrecognized ");
2151 New_Line (Standard_Error);
2157 -----------------------
2158 -- OK_Alphanumerplus --
2159 -----------------------
2161 function OK_Alphanumerplus (S : String) return Boolean is
2163 if S'Length = 0 then
2167 for J in S'Range loop
2168 if not (Is_Alphanumeric (S (J)) or else
2169 S (J) = '_
' or else S (J) = '$
')
2177 end OK_Alphanumerplus;
2183 function OK_Integer (S : String) return Boolean is
2185 if S'Length = 0 then
2189 for J in S'Range loop
2190 if not Is_Digit (S (J)) then
2199 --------------------
2200 -- Output_Version --
2201 --------------------
2203 procedure Output_Version is
2206 Put (Gnatvsn.Gnat_Version_String);
2207 Put_Line (" Copyright 1996-2002 Free Software Foundation, Inc.");
2214 procedure Place (C : Character) is
2216 Buffer.Increment_Last;
2217 Buffer.Table (Buffer.Last) := C;
2219 -- Do not put a space as the first character in the buffer
2220 if C = ' ' and then Buffer.Last = 1 then
2221 Buffer.Decrement_Last;
2225 procedure Place (S : String) is
2227 for J in S'Range loop
2236 procedure Place_Lower (S : String) is
2238 for J in S'Range loop
2239 Place (To_Lower (S (J)));
2243 -------------------------
2244 -- Place_Unix_Switches --
2245 -------------------------
2247 procedure Place_Unix_Switches (S : String_Ptr) is
2248 P1, P2, P3 : Natural;
2254 while P1 <= S'Last loop
2255 if S (P1) = '!' then
2263 pragma Assert (S (P1) = '-' or else S (P1) = '`
');
2265 while P2 < S'Last and then S (P2 + 1) /= ',' loop
2269 -- Switch is now in S (P1 .. P2)
2271 Slen := P2 - P1 + 1;
2275 while P3 <= Buffer.Last - Slen loop
2276 if Buffer.Table (P3) = ' '
2277 and then String (Buffer.Table (P3 + 1 .. P3 + Slen)) =
2279 and then (P3 + Slen = Buffer.Last
2281 Buffer.Table (P3 + Slen + 1) = ' ')
2283 Buffer.Table (P3 .. Buffer.Last - Slen - 1) :=
2284 Buffer.Table (P3 + Slen + 1 .. Buffer.Last);
2285 Buffer.Set_Last (Buffer.Last - Slen - 1);
2295 if S (P1) = '`
' then
2299 Place (S (P1 .. P2));
2304 end Place_Unix_Switches;
2306 ---------------------
2307 -- Set_Library_For --
2308 ---------------------
2310 procedure Set_Library_For
2311 (Project : Project_Id;
2312 There_Are_Libraries : in out Boolean)
2315 -- Case of library project
2317 if Projects.Table (Project).Library then
2318 There_Are_Libraries := True;
2320 -- Add the -L switch
2322 Last_Switches.Increment_Last;
2323 Last_Switches.Table (Last_Switches.Last) :=
2326 (Projects
.Table
(Project
).Library_Dir
));
2328 -- Add the -l switch
2330 Last_Switches
.Increment_Last
;
2331 Last_Switches
.Table
(Last_Switches
.Last
) :=
2334 (Projects.Table (Project).Library_Name));
2336 -- Add the Wl,-rpath switch if library non static
2338 if Projects.Table (Project).Library_Kind /= Static then
2340 Option : constant String_Access :=
2341 MLib.Tgt.Linker_Library_Path_Option
2343 (Projects.Table (Project).Library_Dir));
2346 if Option /= null then
2347 Last_Switches.Increment_Last;
2348 Last_Switches.Table (Last_Switches.Last) :=
2357 end Set_Library_For;
2359 --------------------------------
2360 -- Validate_Command_Or_Option --
2361 --------------------------------
2363 procedure Validate_Command_Or_Option (N : String_Ptr) is
2365 pragma Assert (N'Length > 0);
2367 for J in N'Range loop
2369 pragma Assert (N (J - 1) /= '_
');
2372 pragma Assert (Is_Upper (N (J)) or else Is_Digit (N (J)));
2376 end Validate_Command_Or_Option;
2378 --------------------------
2379 -- Validate_Unix_Switch --
2380 --------------------------
2382 procedure Validate_Unix_Switch (S : String_Ptr) is
2384 if S (S'First) = '`
' then
2388 pragma Assert (S (S'First) = '-' or else S (S'First) = '!');
2390 for J in S'First + 1 .. S'Last loop
2391 pragma Assert (S (J) /= ' ');
2394 pragma Assert (S (J - 1) = ',' and then S (J + 1) = '-');
2398 end Validate_Unix_Switch;
2400 ----------------------
2401 -- List of Commands --
2402 ----------------------
2404 -- Note that we put this after all the local bodies (except Non_VMS_Usage
2405 -- and VMS_Conversion that use Command_List) to avoid some access before
2406 -- elaboration problems.
2408 Command_List : constant array (Real_Command_Type) of Command_Entry :=
2410 (Cname => new S'("BIND"),
2411 Usage
=> new S
'("GNAT BIND file[.ali] /qualifiers"),
2413 Unixcmd => new S'("gnatbind"),
2415 Switches
=> Bind_Switches
'Access,
2416 Params
=> new Parameter_Array
'(1 => File),
2420 (Cname => new S'("CHOP"),
2421 Usage
=> new S
'("GNAT CHOP file [directory] /qualifiers"),
2423 Unixcmd => new S'("gnatchop"),
2425 Switches
=> Chop_Switches
'Access,
2426 Params
=> new Parameter_Array
'(1 => File, 2 => Optional_File),
2430 (Cname => new S'("COMPILE"),
2431 Usage
=> new S
'("GNAT COMPILE filespec[,...] /qualifiers"),
2433 Unixcmd => new S'("gnatmake"),
2434 Unixsws
=> new Argument_List
' (1 => new String'("-f"),
2435 2 => new String'("-u"),
2436 3 => new String'("-c")),
2437 Switches
=> GCC_Switches
'Access,
2438 Params
=> new Parameter_Array
'(1 => Files_Or_Wildcard),
2442 (Cname => new S'("ELIM"),
2443 Usage
=> new S
'("GNAT ELIM name /qualifiers"),
2445 Unixcmd => new S'("gnatelim"),
2447 Switches
=> Elim_Switches
'Access,
2448 Params
=> new Parameter_Array
'(1 => Other_As_Is),
2452 (Cname => new S'("FIND"),
2453 Usage
=> new S
'("GNAT FIND pattern[:sourcefile[:line"
2454 & "[:column]]] filespec[,...] /qualifiers"),
2456 Unixcmd => new S'("gnatfind"),
2458 Switches
=> Find_Switches
'Access,
2459 Params
=> new Parameter_Array
'(1 => Other_As_Is,
2460 2 => Files_Or_Wildcard),
2464 (Cname => new S'("KRUNCH"),
2465 Usage
=> new S
'("GNAT KRUNCH file [/COUNT=nnn]"),
2467 Unixcmd => new S'("gnatkr"),
2469 Switches
=> Krunch_Switches
'Access,
2470 Params
=> new Parameter_Array
'(1 => File),
2474 (Cname => new S'("LIBRARY"),
2475 Usage
=> new S
'("GNAT LIBRARY /[CREATE | SET | DELETE]"
2476 & "=directory [/CONFIG=file]"),
2478 Unixcmd => new S'("gnatlbr"),
2480 Switches
=> Lbr_Switches
'Access,
2481 Params
=> new Parameter_Array
'(1 .. 0 => File),
2485 (Cname => new S'("LINK"),
2486 Usage
=> new S
'("GNAT LINK file[.ali]"
2487 & " [extra obj_&_lib_&_exe_&_opt files]"
2490 Unixcmd => new S'("gnatlink"),
2492 Switches
=> Link_Switches
'Access,
2493 Params
=> new Parameter_Array
'(1 => Unlimited_Files),
2497 (Cname => new S'("LIST"),
2498 Usage
=> new S
'("GNAT LIST /qualifiers object_or_ali_file"),
2500 Unixcmd => new S'("gnatls"),
2502 Switches
=> List_Switches
'Access,
2503 Params
=> new Parameter_Array
'(1 => File),
2507 (Cname => new S'("MAKE"),
2508 Usage
=> new S
'("GNAT MAKE file /qualifiers (includes "
2509 & "COMPILE /qualifiers)"),
2511 Unixcmd => new S'("gnatmake"),
2513 Switches
=> Make_Switches
'Access,
2514 Params
=> new Parameter_Array
'(1 => File),
2518 (Cname => new S'("NAME"),
2519 Usage
=> new S
'("GNAT NAME /qualifiers naming-pattern "
2520 & "[naming-patterns]"),
2522 Unixcmd => new S'("gnatname"),
2524 Switches
=> Name_Switches
'Access,
2525 Params
=> new Parameter_Array
'(1 => Unlimited_As_Is),
2529 (Cname => new S'("PREPROCESS"),
2530 Usage
=> new S
'("GNAT PREPROCESS ifile ofile dfile /qualifiers"),
2532 Unixcmd => new S'("gnatprep"),
2534 Switches
=> Prep_Switches
'Access,
2535 Params
=> new Parameter_Array
'(1 .. 3 => File),
2539 (Cname => new S'("SHARED"),
2540 Usage
=> new S
'("GNAT SHARED [obj_&_lib_&_exe_&_opt"
2541 & "files] /qualifiers"),
2543 Unixcmd => new S'("gcc"),
2544 Unixsws
=> new Argument_List
'(new String'("-shared")
2545 & Init_Object_Dirs
),
2546 Switches
=> Shared_Switches
'Access,
2547 Params
=> new Parameter_Array
'(1 => Unlimited_Files),
2551 (Cname => new S'("STANDARD"),
2552 Usage
=> new S
'("GNAT STANDARD"),
2554 Unixcmd => new S'("gnatpsta"),
2556 Switches
=> Standard_Switches
'Access,
2557 Params
=> new Parameter_Array
'(1 .. 0 => File),
2561 (Cname => new S'("STUB"),
2562 Usage
=> new S
'("GNAT STUB file [directory]/qualifiers"),
2564 Unixcmd => new S'("gnatstub"),
2566 Switches
=> Stub_Switches
'Access,
2567 Params
=> new Parameter_Array
'(1 => File, 2 => Optional_File),
2571 (Cname => new S'("XREF"),
2572 Usage
=> new S
'("GNAT XREF filespec[,...] /qualifiers"),
2574 Unixcmd => new S'("gnatxref"),
2576 Switches
=> Xref_Switches
'Access,
2577 Params
=> new Parameter_Array
'(1 => Files_Or_Wildcard),
2585 procedure Non_VMS_Usage is
2589 Put_Line ("List of available commands");
2592 for C in Command_List'Range loop
2593 if not Command_List (C).VMS_Only then
2594 Put ("GNAT " & Command_List (C).Cname.all);
2596 Put (Command_List (C).Unixcmd.all);
2599 Sws : Argument_List_Access renames Command_List (C).Unixsws;
2602 for J in Sws'Range loop
2614 Put_Line ("Commands FIND, LIST and XREF accept project file " &
2615 "switches -vPx, -Pprj and -Xnam=val");
2619 --------------------
2620 -- VMS_Conversion --
2621 --------------------
2623 procedure VMS_Conversion (The_Command : out Command_Type) is
2627 -- First we must preprocess the string form of the command and options
2628 -- list into the internal form that we use.
2630 for C in Real_Command_Type loop
2633 Command : Item_Ptr := new Command_Item;
2635 Last_Switch : Item_Ptr;
2636 -- Last switch in list
2639 -- Link new command item into list of commands
2641 if Last_Command = null then
2642 Commands := Command;
2644 Last_Command.Next := Command;
2647 Last_Command := Command;
2649 -- Fill in fields of new command item
2651 Command.Name := Command_List (C).Cname;
2652 Command.Usage := Command_List (C).Usage;
2653 Command.Command := C;
2655 if Command_List (C).Unixsws = null then
2656 Command.Unix_String := Command_List (C).Unixcmd;
2659 Cmd : String (1 .. 5_000);
2660 Last : Natural := 0;
2661 Sws : Argument_List_Access := Command_List (C).Unixsws;
2664 Cmd (1 .. Command_List (C).Unixcmd'Length) :=
2665 Command_List (C).Unixcmd.all;
2666 Last := Command_List (C).Unixcmd'Length;
2668 for J in Sws'Range loop
2671 Cmd (Last + 1 .. Last + Sws (J)'Length) :=
2673 Last := Last + Sws (J)'Length;
2676 Command.Unix_String := new String'(Cmd
(1 .. Last
));
2680 Command
.Params
:= Command_List
(C
).Params
;
2681 Command
.Defext
:= Command_List
(C
).Defext
;
2683 Validate_Command_Or_Option
(Command
.Name
);
2685 -- Process the switch list
2687 for S
in Command_List
(C
).Switches
'Range loop
2689 SS
: constant String_Ptr
:= Command_List
(C
).Switches
(S
);
2691 P
: Natural := SS
'First;
2692 Sw
: Item_Ptr
:= new Switch_Item
;
2694 Last_Opt
: Item_Ptr
;
2695 -- Pointer to last option
2698 -- Link new switch item into list of switches
2700 if Last_Switch
= null then
2701 Command
.Switches
:= Sw
;
2703 Last_Switch
.Next
:= Sw
;
2708 -- Process switch string, first get name
2710 while SS
(P
) /= ' ' and SS
(P
) /= '=' loop
2714 Sw
.Name
:= new String'(SS (SS'First .. P - 1));
2716 -- Direct translation case
2718 if SS (P) = ' ' then
2719 Sw.Translation := T_Direct;
2720 Sw.Unix_String := new String'(SS
(P
+ 1 .. SS
'Last));
2721 Validate_Unix_Switch
(Sw
.Unix_String
);
2723 if SS
(P
- 1) = '>' then
2724 Sw
.Translation
:= T_Other
;
2726 elsif SS
(P
+ 1) = '`' then
2729 -- Create the inverted case (/NO ..)
2731 elsif SS
(SS
'First + 1 .. SS
'First + 2) /= "NO" then
2732 Sw
:= new Switch_Item
;
2733 Last_Switch
.Next
:= Sw
;
2737 new String'("/NO" & SS (SS'First + 1 .. P - 1));
2738 Sw.Translation := T_Direct;
2739 Sw.Unix_String := Invert_Sense (SS (P + 1 .. SS'Last));
2740 Validate_Unix_Switch (Sw.Unix_String);
2743 -- Directories translation case
2745 elsif SS (P + 1) = '*' then
2746 pragma Assert (SS (SS'Last) = '*');
2747 Sw.Translation := T_Directories;
2748 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2749 Validate_Unix_Switch
(Sw
.Unix_String
);
2751 -- Directory translation case
2753 elsif SS
(P
+ 1) = '%' then
2754 pragma Assert
(SS
(SS
'Last) = '%');
2755 Sw
.Translation
:= T_Directory
;
2756 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2757 Validate_Unix_Switch (Sw.Unix_String);
2759 -- File translation case
2761 elsif SS (P + 1) = '@
' then
2762 pragma Assert (SS (SS'Last) = '@
');
2763 Sw.Translation := T_File;
2764 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2765 Validate_Unix_Switch
(Sw
.Unix_String
);
2767 -- No space file translation case
2769 elsif SS
(P
+ 1) = '<' then
2770 pragma Assert
(SS
(SS
'Last) = '>');
2771 Sw
.Translation
:= T_No_Space_File
;
2772 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2773 Validate_Unix_Switch (Sw.Unix_String);
2775 -- Numeric translation case
2777 elsif SS (P + 1) = '#
' then
2778 pragma Assert (SS (SS'Last) = '#
');
2779 Sw.Translation := T_Numeric;
2780 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2781 Validate_Unix_Switch
(Sw
.Unix_String
);
2783 -- Alphanumerplus translation case
2785 elsif SS
(P
+ 1) = '|' then
2786 pragma Assert
(SS
(SS
'Last) = '|');
2787 Sw
.Translation
:= T_Alphanumplus
;
2788 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2789 Validate_Unix_Switch (Sw.Unix_String);
2791 -- String translation case
2793 elsif SS (P + 1) = '"' then
2794 pragma Assert (SS (SS'Last) = '"');
2795 Sw.Translation := T_String;
2796 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2797 Validate_Unix_Switch
(Sw
.Unix_String
);
2799 -- Commands translation case
2801 elsif SS
(P
+ 1) = '?' then
2802 Sw
.Translation
:= T_Commands
;
2803 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last));
2805 -- Options translation case
2808 Sw.Translation := T_Options;
2809 Sw.Unix_String := new String'("");
2811 P
:= P
+ 1; -- bump past =
2812 while P
<= SS
'Last loop
2814 Opt
: Item_Ptr
:= new Option_Item
;
2818 -- Link new option item into options list
2820 if Last_Opt
= null then
2823 Last_Opt
.Next
:= Opt
;
2828 -- Fill in fields of new option item
2831 while SS
(Q
) /= ' ' loop
2835 Opt
.Name
:= new String'(SS (P .. Q - 1));
2836 Validate_Command_Or_Option (Opt.Name);
2841 while Q <= SS'Last and then SS (Q) /= ' ' loop
2845 Opt.Unix_String := new String'(SS
(P
.. Q
- 1));
2846 Validate_Unix_Switch
(Opt
.Unix_String
);
2856 -- If no parameters, give complete list of commands
2858 if Argument_Count
= 0 then
2861 Put_Line
("List of available commands");
2864 while Commands
/= null loop
2865 Put
(Commands
.Usage
.all);
2867 Put_Line
(Commands
.Unix_String
.all);
2868 Commands
:= Commands
.Next
;
2876 -- Loop through arguments
2878 while Arg_Num
<= Argument_Count
loop
2880 Process_Argument
: declare
2881 Argv
: String_Access
;
2884 function Get_Arg_End
2888 -- Begins looking at Arg_Idx + 1 and returns the index of the
2889 -- last character before a slash or else the index of the last
2890 -- character in the string Argv.
2896 function Get_Arg_End
2902 for J
in Arg_Idx
+ 1 .. Argv
'Last loop
2903 if Argv
(J
) = '/' then
2911 -- Start of processing for Process_Argument
2914 Argv
:= new String'(Argument (Arg_Num));
2915 Arg_Idx := Argv'First;
2917 <<Tryagain_After_Coalesce>>
2920 Next_Arg_Idx : Integer;
2921 Arg : String_Access;
2924 Next_Arg_Idx := Get_Arg_End (Argv.all, Arg_Idx);
2925 Arg := new String'(Argv
(Arg_Idx
.. Next_Arg_Idx
));
2927 -- The first one must be a command name
2929 if Arg_Num
= 1 and then Arg_Idx
= Argv
'First then
2931 Command
:= Matching_Name
(Arg
.all, Commands
);
2933 if Command
= null then
2937 The_Command
:= Command
.Command
;
2939 -- Give usage information if only command given
2941 if Argument_Count
= 1 and then Next_Arg_Idx
= Argv
'Last
2942 and then Command
.Command
/= Standard
2947 ("List of available qualifiers and options");
2950 Put
(Command
.Usage
.all);
2952 Put_Line
(Command
.Unix_String
.all);
2955 Sw
: Item_Ptr
:= Command
.Switches
;
2958 while Sw
/= null loop
2962 case Sw
.Translation
is
2966 Put_Line
(Sw
.Unix_String
.all &
2971 Put_Line
(Sw
.Unix_String
.all);
2973 when T_Directories
=>
2974 Put
("=(direc,direc,..direc)");
2976 Put
(Sw
.Unix_String
.all);
2978 Put
(Sw
.Unix_String
.all);
2979 Put_Line
(" direc ...");
2984 Put
(Sw
.Unix_String
.all);
2986 if Sw
.Unix_String
(Sw
.Unix_String
'Last)
2992 Put_Line
("directory ");
2994 when T_File | T_No_Space_File
=>
2997 Put
(Sw
.Unix_String
.all);
2999 if Sw
.Translation
= T_File
3000 and then Sw
.Unix_String
3001 (Sw
.Unix_String
'Last)
3013 if Sw
.Unix_String
(Sw
.Unix_String
'First)
3017 (Sw
.Unix_String
'First + 1
3018 .. Sw
.Unix_String
'Last));
3020 Put
(Sw
.Unix_String
.all);
3025 when T_Alphanumplus
=>
3029 if Sw
.Unix_String
(Sw
.Unix_String
'First)
3033 (Sw
.Unix_String
'First + 1
3034 .. Sw
.Unix_String
'Last));
3036 Put
(Sw
.Unix_String
.all);
3048 Put
(Sw
.Unix_String
.all);
3050 if Sw
.Unix_String
(Sw
.Unix_String
'Last)
3060 Put
(" (switches for ");
3062 (Sw
.Unix_String
'First + 7
3063 .. Sw
.Unix_String
'Last));
3067 (Sw
.Unix_String
'First
3068 .. Sw
.Unix_String
'First + 5));
3069 Put_Line
(" switches");
3073 Opt
: Item_Ptr
:= Sw
.Options
;
3076 Put_Line
("=(option,option..)");
3078 while Opt
/= null loop
3082 if Opt
= Sw
.Options
then
3087 Put_Line
(Opt
.Unix_String
.all);
3101 -- Place (Command.Unix_String.all);
3103 -- Special handling for internal debugging switch /?
3105 elsif Arg
.all = "/?" then
3106 Display_Command
:= True;
3108 -- Copy -switch unchanged
3110 elsif Arg
(Arg
'First) = '-' then
3114 -- Copy quoted switch with quotes stripped
3116 elsif Arg
(Arg
'First) = '"' then
3117 if Arg
(Arg
'Last) /= '"' then
3118 Put
(Standard_Error
, "misquoted argument: ");
3119 Put_Line
(Standard_Error
, Arg
.all);
3120 Errors
:= Errors
+ 1;
3124 Place
(Arg
(Arg
'First + 1 .. Arg
'Last - 1));
3127 -- Parameter Argument
3129 elsif Arg
(Arg
'First) /= '/'
3130 and then Make_Commands_Active
= null
3132 Param_Count
:= Param_Count
+ 1;
3134 if Param_Count
<= Command
.Params
'Length then
3136 case Command
.Params
(Param_Count
) is
3138 when File | Optional_File
=>
3140 Normal_File
: String_Access
3141 := To_Canonical_File_Spec
(Arg
.all);
3144 Place_Lower
(Normal_File
.all);
3146 if Is_Extensionless
(Normal_File
.all)
3147 and then Command
.Defext
/= " "
3150 Place
(Command
.Defext
);
3154 when Unlimited_Files
=>
3156 Normal_File
: String_Access
3157 := To_Canonical_File_Spec
(Arg
.all);
3159 File_Is_Wild
: Boolean := False;
3160 File_List
: String_Access_List_Access
;
3162 for I
in Arg
'Range loop
3164 or else Arg
(I
) = '%'
3166 File_Is_Wild
:= True;
3170 if File_Is_Wild
then
3171 File_List
:= To_Canonical_File_List
3174 for I
in File_List
.all'Range loop
3176 Place_Lower
(File_List
.all (I
).all);
3180 Place_Lower
(Normal_File
.all);
3182 if Is_Extensionless
(Normal_File
.all)
3183 and then Command
.Defext
/= " "
3186 Place
(Command
.Defext
);
3190 Param_Count
:= Param_Count
- 1;
3197 when Unlimited_As_Is
=>
3200 Param_Count
:= Param_Count
- 1;
3202 when Files_Or_Wildcard
=>
3204 -- Remove spaces from a comma separated list
3205 -- of file names and adjust control variables
3208 while Arg_Num
< Argument_Count
and then
3209 (Argv
(Argv
'Last) = ',' xor
3210 Argument
(Arg_Num
+ 1)
3211 (Argument
(Arg_Num
+ 1)'First) = ',')
3214 (Argv.all & Argument (Arg_Num + 1));
3215 Arg_Num := Arg_Num + 1;
3216 Arg_Idx := Argv'First;
3218 Get_Arg_End (Argv.all, Arg_Idx);
3220 (Argv
(Arg_Idx
.. Next_Arg_Idx
));
3223 -- Parse the comma separated list of VMS
3224 -- filenames and place them on the command
3225 -- line as space separated Unix style
3226 -- filenames. Lower case and add default
3227 -- extension as appropriate.
3230 Arg1_Idx
: Integer := Arg
'First;
3232 function Get_Arg1_End
3233 (Arg
: String; Arg_Idx
: Integer)
3235 -- Begins looking at Arg_Idx + 1 and
3236 -- returns the index of the last character
3237 -- before a comma or else the index of the
3238 -- last character in the string Arg.
3240 function Get_Arg1_End
3241 (Arg
: String; Arg_Idx
: Integer)
3245 for I
in Arg_Idx
+ 1 .. Arg
'Last loop
3246 if Arg
(I
) = ',' then
3257 Next_Arg1_Idx
: Integer :=
3258 Get_Arg1_End
(Arg
.all, Arg1_Idx
);
3261 Arg
(Arg1_Idx
.. Next_Arg1_Idx
);
3263 Normal_File
: String_Access
:=
3264 To_Canonical_File_Spec
(Arg1
);
3268 Place_Lower
(Normal_File
.all);
3270 if Is_Extensionless
(Normal_File
.all)
3271 and then Command
.Defext
/= " "
3274 Place
(Command
.Defext
);
3277 Arg1_Idx
:= Next_Arg1_Idx
+ 1;
3280 exit when Arg1_Idx
> Arg
'Last;
3282 -- Don't allow two or more commas in
3285 if Arg
(Arg1_Idx
) = ',' then
3286 Arg1_Idx
:= Arg1_Idx
+ 1;
3287 if Arg1_Idx
> Arg
'Last or else
3288 Arg
(Arg1_Idx
) = ','
3292 "Malformed Parameter: " &
3294 Put
(Standard_Error
, "usage: ");
3295 Put_Line
(Standard_Error
,
3306 -- Qualifier argument
3313 Endp
: Natural := 0; -- avoid warning!
3318 while SwP
< Arg
'Last
3319 and then Arg
(SwP
+ 1) /= '='
3324 -- At this point, the switch name is in
3325 -- Arg (Arg'First..SwP) and if that is not the
3326 -- whole switch, then there is an equal sign at
3327 -- Arg (SwP + 1) and the rest of Arg is what comes
3328 -- after the equal sign.
3330 -- If make commands are active, see if we have
3331 -- another COMMANDS_TRANSLATION switch belonging
3334 if Make_Commands_Active
/= null then
3337 (Arg
(Arg
'First .. SwP
),
3342 and then Sw
.Translation
= T_Commands
3349 (Arg
(Arg
'First .. SwP
),
3350 Make_Commands_Active
.Switches
,
3354 -- For case of GNAT MAKE or CHOP, if we cannot
3355 -- find the switch, then see if it is a
3356 -- recognized compiler switch instead, and if
3357 -- so process the compiler switch.
3359 elsif Command
.Name
.all = "MAKE"
3360 or else Command
.Name
.all = "CHOP" then
3363 (Arg
(Arg
'First .. SwP
),
3370 (Arg
(Arg
'First .. SwP
),
3372 ("COMPILE", Commands
).Switches
,
3376 -- For all other cases, just search the relevant
3382 (Arg
(Arg
'First .. SwP
),
3388 case Sw
.Translation
is
3391 Place_Unix_Switches
(Sw
.Unix_String
);
3393 and then Arg
(SwP
+ 1) = '='
3395 Put
(Standard_Error
,
3396 "qualifier options ignored: ");
3397 Put_Line
(Standard_Error
, Arg
.all);
3400 when T_Directories
=>
3401 if SwP
+ 1 > Arg
'Last then
3402 Put
(Standard_Error
,
3403 "missing directories for: ");
3404 Put_Line
(Standard_Error
, Arg
.all);
3405 Errors
:= Errors
+ 1;
3407 elsif Arg
(SwP
+ 2) /= '(' then
3411 elsif Arg
(Arg
'Last) /= ')' then
3413 -- Remove spaces from a comma separated
3414 -- list of file names and adjust
3415 -- control variables accordingly.
3417 if Arg_Num
< Argument_Count
and then
3418 (Argv
(Argv
'Last) = ',' xor
3419 Argument
(Arg_Num
+ 1)
3420 (Argument
(Arg_Num
+ 1)'First) = ',')
3423 new String'(Argv.all
3426 Arg_Num := Arg_Num + 1;
3427 Arg_Idx := Argv'First;
3429 := Get_Arg_End (Argv.all, Arg_Idx);
3431 (Argv
(Arg_Idx
.. Next_Arg_Idx
));
3432 goto Tryagain_After_Coalesce
;
3435 Put
(Standard_Error
,
3436 "incorrectly parenthesized " &
3437 "or malformed argument: ");
3438 Put_Line
(Standard_Error
, Arg
.all);
3439 Errors
:= Errors
+ 1;
3443 Endp
:= Arg
'Last - 1;
3446 while SwP
<= Endp
loop
3448 Dir_Is_Wild
: Boolean := False;
3449 Dir_Maybe_Is_Wild
: Boolean := False;
3450 Dir_List
: String_Access_List_Access
;
3455 and then Arg
(P2
+ 1) /= ','
3458 -- A wildcard directory spec on
3459 -- VMS will contain either * or
3462 if Arg
(P2
) = '*' then
3463 Dir_Is_Wild
:= True;
3465 elsif Arg
(P2
) = '%' then
3466 Dir_Is_Wild
:= True;
3468 elsif Dir_Maybe_Is_Wild
3469 and then Arg
(P2
) = '.'
3470 and then Arg
(P2
+ 1) = '.'
3472 Dir_Is_Wild
:= True;
3473 Dir_Maybe_Is_Wild
:= False;
3475 elsif Dir_Maybe_Is_Wild
then
3476 Dir_Maybe_Is_Wild
:= False;
3478 elsif Arg
(P2
) = '.'
3479 and then Arg
(P2
+ 1) = '.'
3481 Dir_Maybe_Is_Wild
:= True;
3488 if (Dir_Is_Wild
) then
3489 Dir_List
:= To_Canonical_File_List
3490 (Arg
(SwP
.. P2
), True);
3492 for I
in Dir_List
.all'Range loop
3496 (Dir_List
.all (I
).all);
3502 (To_Canonical_Dir_Spec
3503 (Arg
(SwP
.. P2
), False).all);
3511 if SwP
+ 1 > Arg
'Last then
3512 Put
(Standard_Error
,
3513 "missing directory for: ");
3514 Put_Line
(Standard_Error
, Arg
.all);
3515 Errors
:= Errors
+ 1;
3518 Place_Unix_Switches
(Sw
.Unix_String
);
3520 -- Some switches end in "=". No space
3524 (Sw
.Unix_String
'Last) /= '='
3530 (To_Canonical_Dir_Spec
3531 (Arg
(SwP
+ 2 .. Arg
'Last),
3535 when T_File | T_No_Space_File
=>
3536 if SwP
+ 1 > Arg
'Last then
3537 Put
(Standard_Error
,
3538 "missing file for: ");
3539 Put_Line
(Standard_Error
, Arg
.all);
3540 Errors
:= Errors
+ 1;
3543 Place_Unix_Switches
(Sw
.Unix_String
);
3545 -- Some switches end in "=". No space
3548 if Sw
.Translation
= T_File
3549 and then Sw
.Unix_String
3550 (Sw
.Unix_String
'Last) /= '='
3556 (To_Canonical_File_Spec
3557 (Arg
(SwP
+ 2 .. Arg
'Last)).all);
3562 OK_Integer
(Arg
(SwP
+ 2 .. Arg
'Last))
3564 Place_Unix_Switches
(Sw
.Unix_String
);
3565 Place
(Arg
(SwP
+ 2 .. Arg
'Last));
3568 Put
(Standard_Error
, "argument for ");
3569 Put
(Standard_Error
, Sw
.Name
.all);
3571 (Standard_Error
, " must be numeric");
3572 Errors
:= Errors
+ 1;
3575 when T_Alphanumplus
=>
3578 (Arg
(SwP
+ 2 .. Arg
'Last))
3580 Place_Unix_Switches
(Sw
.Unix_String
);
3581 Place
(Arg
(SwP
+ 2 .. Arg
'Last));
3584 Put
(Standard_Error
, "argument for ");
3585 Put
(Standard_Error
, Sw
.Name
.all);
3586 Put_Line
(Standard_Error
,
3587 " must be alphanumeric");
3588 Errors
:= Errors
+ 1;
3593 -- A String value must be extended to the
3594 -- end of the Argv, otherwise strings like
3595 -- "foo/bar" get split at the slash.
3597 -- The begining and ending of the string
3598 -- are flagged with embedded nulls which
3599 -- are removed when building the Spawn
3600 -- call. Nulls are use because they won't
3601 -- show up in a /? output. Quotes aren't
3602 -- used because that would make it
3603 -- difficult to embed them.
3605 Place_Unix_Switches
(Sw
.Unix_String
);
3606 if Next_Arg_Idx
/= Argv
'Last then
3607 Next_Arg_Idx
:= Argv
'Last;
3609 (Argv (Arg_Idx .. Next_Arg_Idx));
3612 while SwP < Arg'Last and then
3613 Arg (SwP + 1) /= '=' loop
3618 Place (Arg (SwP + 2 .. Arg'Last));
3623 -- Output -largs/-bargs/-cargs
3626 Place (Sw.Unix_String
3627 (Sw.Unix_String'First ..
3628 Sw.Unix_String'First + 5));
3630 -- Set source of new commands, also
3631 -- setting this non-null indicates that
3632 -- we are in the special commands mode
3633 -- for processing the -xargs case.
3635 Make_Commands_Active :=
3638 (Sw.Unix_String'First + 7 ..
3639 Sw.Unix_String'Last),
3643 if SwP + 1 > Arg'Last then
3645 (Sw.Options.Unix_String);
3648 elsif Arg (SwP + 2) /= '(' then
3652 elsif Arg (Arg'Last) /= ')' then
3655 "incorrectly parenthesized " &
3657 Put_Line (Standard_Error, Arg.all);
3658 Errors := Errors + 1;
3663 Endp := Arg'Last - 1;
3666 while SwP <= Endp loop
3670 and then Arg (P2 + 1) /= ','
3675 -- Option name is in Arg (SwP .. P2)
3677 Opt := Matching_Name (Arg (SwP .. P2),
3690 (new String'(Sw
.Unix_String
.all &
3698 Arg_Idx
:= Next_Arg_Idx
+ 1;
3701 exit when Arg_Idx
> Argv
'Last;
3704 end Process_Argument
;
3706 Arg_Num
:= Arg_Num
+ 1;
3709 if Display_Command
then
3710 Put
(Standard_Error
, "generated command -->");
3711 Put
(Standard_Error
, Command_List
(The_Command
).Unixcmd
.all);
3713 if Command_List
(The_Command
).Unixsws
/= null then
3714 for J
in Command_List
(The_Command
).Unixsws
'Range loop
3715 Put
(Standard_Error
, " ");
3716 Put
(Standard_Error
,
3717 Command_List
(The_Command
).Unixsws
(J
).all);
3721 Put
(Standard_Error
, " ");
3722 Put
(Standard_Error
, String (Buffer
.Table
(1 .. Buffer
.Last
)));
3723 Put
(Standard_Error
, "<--");
3724 New_Line
(Standard_Error
);
3728 -- Gross error checking that the number of parameters is correct.
3729 -- Not applicable to Unlimited_Files parameters.
3731 if (Param_Count
= Command
.Params
'Length - 1
3732 and then Command
.Params
(Param_Count
+ 1) = Unlimited_Files
)
3733 or else Param_Count
<= Command
.Params
'Length
3738 Put_Line
(Standard_Error
,
3739 "Parameter count of "
3740 & Integer'Image (Param_Count
)
3741 & " not equal to expected "
3742 & Integer'Image (Command
.Params
'Length));
3743 Put
(Standard_Error
, "usage: ");
3744 Put_Line
(Standard_Error
, Command
.Usage
.all);
3745 Errors
:= Errors
+ 1;
3751 -- Prepare arguments for a call to spawn, filtering out
3752 -- embedded nulls place there to delineate strings.
3756 Inside_Nul
: Boolean := False;
3757 Arg
: String (1 .. 1024);
3763 while P1
<= Buffer
.Last
and then Buffer
.Table
(P1
) = ' ' loop
3768 Arg
(Arg_Ctr
) := Buffer
.Table
(P1
);
3770 while P1
<= Buffer
.Last
loop
3772 if Buffer
.Table
(P1
) = ASCII
.NUL
then
3774 Inside_Nul
:= False;
3780 if Buffer
.Table
(P1
) = ' ' and then not Inside_Nul
then
3782 Arg_Ctr
:= Arg_Ctr
+ 1;
3783 Arg
(Arg_Ctr
) := Buffer
.Table
(P1
);
3786 Last_Switches
.Increment_Last
;
3789 while P2
< Buffer
.Last
3790 and then (Buffer
.Table
(P2
+ 1) /= ' ' or else
3794 Arg_Ctr
:= Arg_Ctr
+ 1;
3795 Arg
(Arg_Ctr
) := Buffer
.Table
(P2
);
3796 if Buffer
.Table
(P2
) = ASCII
.NUL
then
3797 Arg_Ctr
:= Arg_Ctr
- 1;
3799 Inside_Nul
:= False;
3806 Last_Switches
.Table
(Last_Switches
.Last
) :=
3807 new String'(String (Arg (1 .. Arg_Ctr)));
3810 Arg (Arg_Ctr) := Buffer.Table (P1);
3817 -------------------------------------
3818 -- Start of processing for GNATCmd --
3819 -------------------------------------
3832 Last_Switches.Set_Last (0);
3834 First_Switches.Init;
3835 First_Switches.Set_Last (0);
3837 -- If on VMS, or if VMS emulation is on, convert VMS style /qualifiers,
3838 -- filenames and pathnames to Unix style.
3841 or else To_Lower (Getenv ("EMULATE_VMS").all) = "true"
3843 VMS_Conversion (The_Command);
3845 -- If not on VMS, scan the command line directly
3848 if Argument_Count = 0 then
3853 if Argument_Count > 1 and then Argument (1) = "-v" then
3854 Opt.Verbose_Mode := True;
3858 The_Command := Real_Command_Type'Value (Argument (Command_Arg));
3860 if Command_List (The_Command).VMS_Only then
3862 Fail ("Command """ & Command_List (The_Command).Cname.all &
3863 """ can only be used on VMS");
3866 when Constraint_Error =>
3868 -- Check if it is an alternate command
3870 Alternate : Alternate_Command;
3873 Alternate := Alternate_Command'Value
3874 (Argument (Command_Arg));
3875 The_Command := Corresponding_To (Alternate);
3878 when Constraint_Error =>
3880 Fail ("Unknown command: " & Argument (Command_Arg));
3884 for Arg in Command_Arg + 1 .. Argument_Count loop
3885 Last_Switches.Increment_Last;
3886 Last_Switches.Table (Last_Switches.Last) :=
3887 new String'(Argument
(Arg
));
3893 Program
: constant String :=
3894 Program_Name
(Command_List
(The_Command
).Unixcmd
.all).all;
3896 Exec_Path
: String_Access
;
3899 -- Locate the executable for the command
3901 Exec_Path
:= Locate_Exec_On_Path
(Program
);
3903 if Exec_Path
= null then
3904 Put_Line
(Standard_Error
, "Couldn't locate " & Program
);
3908 -- If there are switches for the executable, put them as first switches
3910 if Command_List
(The_Command
).Unixsws
/= null then
3911 for J
in Command_List
(The_Command
).Unixsws
'Range loop
3912 First_Switches
.Increment_Last
;
3913 First_Switches
.Table
(First_Switches
.Last
) :=
3914 Command_List
(The_Command
).Unixsws
(J
);
3918 -- For BIND, FIND, LINK, LIST and XREF, look for project file related
3921 if The_Command
= Bind
3922 or else The_Command
= Find
3923 or else The_Command
= Link
3924 or else The_Command
= List
3925 or else The_Command
= Xref
3929 Tool_Package_Name
:= Name_Binder
;
3931 Tool_Package_Name
:= Name_Finder
;
3933 Tool_Package_Name
:= Name_Linker
;
3935 Tool_Package_Name
:= Name_Gnatls
;
3937 Tool_Package_Name
:= Name_Cross_Reference
;
3943 Arg_Num
: Positive := 1;
3944 Argv
: String_Access
;
3946 procedure Remove_Switch
(Num
: Positive);
3947 -- Remove a project related switch from table Last_Switches
3953 procedure Remove_Switch
(Num
: Positive) is
3955 Last_Switches
.Table
(Num
.. Last_Switches
.Last
- 1) :=
3956 Last_Switches
.Table
(Num
+ 1 .. Last_Switches
.Last
);
3957 Last_Switches
.Decrement_Last
;
3960 -- Start of processing for ??? (need block name here)
3963 while Arg_Num
<= Last_Switches
.Last
loop
3964 Argv
:= Last_Switches
.Table
(Arg_Num
);
3966 if Argv
(Argv
'First) = '-' then
3967 if Argv
'Length = 1 then
3968 Fail
("switch character cannot be followed by a blank");
3971 -- The two style project files (-p and -P) cannot be used
3974 if (The_Command
= Find
or else The_Command
= Xref
)
3975 and then Argv
(2) = 'p'
3977 Old_Project_File_Used
:= True;
3978 if Project_File
/= null then
3979 Fail
("-P and -p cannot be used together");
3983 -- -vPx Specify verbosity while parsing project files
3986 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "vP"
3988 case Argv
(Argv
'Last) is
3990 Current_Verbosity
:= Prj
.Default
;
3992 Current_Verbosity
:= Prj
.Medium
;
3994 Current_Verbosity
:= Prj
.High
;
3996 Fail
("Invalid switch: " & Argv
.all);
3999 Remove_Switch
(Arg_Num
);
4001 -- -Pproject_file Specify project file to be used
4003 elsif Argv
'Length >= 3
4004 and then Argv
(Argv
'First + 1) = 'P'
4007 -- Only one -P switch can be used
4009 if Project_File
/= null then
4011 ": second project file forbidden (first is """ &
4012 Project_File
.all & """)");
4014 -- The two style project files (-p and -P) cannot be
4017 elsif Old_Project_File_Used
then
4018 Fail
("-p and -P cannot be used together");
4022 new String'(Argv (Argv'First + 2 .. Argv'Last));
4025 Remove_Switch (Arg_Num);
4027 -- -Xexternal=value Specify an external reference to be
4028 -- used in project files
4030 elsif Argv'Length >= 5
4031 and then Argv (Argv'First + 1) = 'X
'
4034 Equal_Pos : constant Natural :=
4035 Index ('=', Argv (Argv'First + 2 .. Argv'Last));
4037 if Equal_Pos >= Argv'First + 3 and then
4038 Equal_Pos /= Argv'Last then
4039 Add (External_Name =>
4040 Argv (Argv'First + 2 .. Equal_Pos - 1),
4041 Value => Argv (Equal_Pos + 1 .. Argv'Last));
4044 " is not a valid external assignment.");
4048 Remove_Switch (Arg_Num);
4051 Arg_Num := Arg_Num + 1;
4055 Arg_Num := Arg_Num + 1;
4061 -- If there is a project file specified, parse it, get the switches
4062 -- for the tool and setup PATH environment variables.
4064 if Project_File /= null then
4065 Prj.Pars.Set_Verbosity (To => Current_Verbosity);
4068 (Project => Project,
4069 Project_File_Name => Project_File.all);
4071 if Project = Prj.No_Project then
4072 Fail ("""" & Project_File.all & """ processing failed");
4075 -- Check if a package with the name of the tool is in the project
4076 -- file and if there is one, get the switches, if any, and scan them.
4079 Data : Prj.Project_Data := Prj.Projects.Table (Project);
4080 Pkg : Prj.Package_Id :=
4082 (Name => Tool_Package_Name,
4083 In_Packages => Data.Decl.Packages);
4085 Element : Package_Element;
4087 Default_Switches_Array : Array_Element_Id;
4089 The_Switches : Prj.Variable_Value;
4090 Current : Prj.String_List_Id;
4091 The_String : String_Element;
4094 if Pkg /= No_Package then
4095 Element := Packages.Table (Pkg);
4097 -- Packages Gnatls has a single attribute Switches, that is
4098 -- not an associative array.
4100 if The_Command = List then
4103 (Variable_Name => Snames.Name_Switches,
4104 In_Variables => Element.Decl.Attributes);
4106 -- Packages Binder (for gnatbind), Cross_Reference (for
4107 -- gnatxref), Linker (for gnatlink) and Finder
4108 -- (for gnatfind) have an attributed Default_Switches,
4109 -- an associative array, indexed by the name of the
4110 -- programming language.
4112 Default_Switches_Array :=
4114 (Name => Name_Default_Switches,
4115 In_Arrays => Packages.Table (Pkg).Decl.Arrays);
4116 The_Switches := Prj.Util.Value_Of
4118 In_Array => Default_Switches_Array);
4122 -- If there are switches specified in the package of the
4123 -- project file corresponding to the tool, scan them.
4125 case The_Switches.Kind is
4126 when Prj.Undefined =>
4130 if String_Length (The_Switches.Value) > 0 then
4131 String_To_Name_Buffer (The_Switches.Value);
4132 First_Switches.Increment_Last;
4133 First_Switches.Table (First_Switches.Last) :=
4134 new String'(Name_Buffer
(1 .. Name_Len
));
4138 Current
:= The_Switches
.Values
;
4139 while Current
/= Prj
.Nil_String
loop
4140 The_String
:= String_Elements
.Table
(Current
);
4142 if String_Length
(The_String
.Value
) > 0 then
4143 String_To_Name_Buffer
(The_String
.Value
);
4144 First_Switches
.Increment_Last
;
4145 First_Switches
.Table
(First_Switches
.Last
) :=
4146 new String'(Name_Buffer (1 .. Name_Len));
4149 Current := The_String.Next;
4155 -- Set up the environment variables ADA_INCLUDE_PATH and
4156 -- ADA_OBJECTS_PATH.
4159 (Name => Ada_Include_Path,
4160 Value => Prj.Env.Ada_Include_Path (Project).all);
4162 (Name => Ada_Objects_Path,
4163 Value => Prj.Env.Ada_Objects_Path
4164 (Project, Including_Libraries => False).all);
4166 if The_Command = Bind or else The_Command = Link then
4169 (Projects.Table (Project).Object_Directory));
4172 if The_Command = Link then
4174 -- Add the default search directories, to be able to find
4175 -- libgnat in call to MLib.Utl.Lib_Directory.
4177 Add_Default_Search_Dirs;
4180 There_Are_Libraries : Boolean := False;
4183 -- Check if there are library project files
4185 if MLib.Tgt.Libraries_Are_Supported then
4186 Set_Libraries (Project, There_Are_Libraries);
4189 -- If there are, add the necessary additional switches
4191 if There_Are_Libraries then
4193 -- Add -L<lib_dir> -lgnarl -lgnat -Wl,-rpath,<lib_dir>
4195 Last_Switches.Increment_Last;
4196 Last_Switches.Table (Last_Switches.Last) :=
4197 new String'("-L" & MLib
.Utl
.Lib_Directory
);
4198 Last_Switches
.Increment_Last
;
4199 Last_Switches
.Table
(Last_Switches
.Last
) :=
4200 new String'("-lgnarl");
4201 Last_Switches.Increment_Last;
4202 Last_Switches.Table (Last_Switches.Last) :=
4203 new String'("-lgnat");
4206 Option
: constant String_Access
:=
4207 MLib
.Tgt
.Linker_Library_Path_Option
4208 (MLib
.Utl
.Lib_Directory
);
4211 if Option
/= null then
4212 Last_Switches
.Increment_Last
;
4213 Last_Switches
.Table
(Last_Switches
.Last
) :=
4222 -- Gather all the arguments and invoke the executable
4225 The_Args
: Argument_List
4226 (1 .. First_Switches
.Last
+ Last_Switches
.Last
);
4227 Arg_Num
: Natural := 0;
4229 for J
in 1 .. First_Switches
.Last
loop
4230 Arg_Num
:= Arg_Num
+ 1;
4231 The_Args
(Arg_Num
) := First_Switches
.Table
(J
);
4234 for J
in 1 .. Last_Switches
.Last
loop
4235 Arg_Num
:= Arg_Num
+ 1;
4236 The_Args
(Arg_Num
) := Last_Switches
.Table
(J
);
4239 if Opt
.Verbose_Mode
then
4240 Output
.Write_Str
(Exec_Path
.all);
4242 for Arg
in The_Args
'Range loop
4243 Output
.Write_Char
(' ');
4244 Output
.Write_Str
(The_Args
(Arg
).all);
4251 := Exit_Status
(Spawn
(Exec_Path
.all, The_Args
));
4258 Set_Exit_Status
(Failure
);
4261 Set_Exit_Status
(My_Exit_Status
);