1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
10 -- Copyright (C) 1996-2002 Free Software Foundation, Inc. --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
26 ------------------------------------------------------------------------------
28 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
33 with Namet
; use Namet
;
35 with Osint
; use Osint
;
39 with Prj
.Ext
; use Prj
.Ext
;
41 with Prj
.Util
; use Prj
.Util
;
42 with Sdefault
; use Sdefault
;
43 with Snames
; use Snames
;
44 with Stringt
; use Stringt
;
46 with Types
; use Types
;
47 with Hostparm
; use Hostparm
;
48 -- Used to determine if we are in VMS or not for error message purposes
50 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
51 with Ada
.Command_Line
; use Ada
.Command_Line
;
52 with Ada
.Text_IO
; use Ada
.Text_IO
;
55 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
61 Ada_Include_Path
: constant String := "ADA_INCLUDE_PATH";
62 Ada_Objects_Path
: constant String := "ADA_OBJECTS_PATH";
64 Project_File
: String_Access
;
65 Project
: Prj
.Project_Id
;
66 Current_Verbosity
: Prj
.Verbosity
:= Prj
.Default
;
67 Tool_Package_Name
: Name_Id
:= No_Name
;
69 -- This flag indicates a switch -p (for gnatxref and gnatfind) for
70 -- an old fashioned project file. -p cannot be used in conjonction
73 Old_Project_File_Used
: Boolean := False;
75 -- A table to keep the switches on the command line
77 package Last_Switches
is new Table
.Table
78 (Table_Component_Type
=> String_Access
,
79 Table_Index_Type
=> Integer,
82 Table_Increment
=> 100,
83 Table_Name
=> "Gnatcmd.Last_Switches");
85 -- A table to keep the switches from the project file
87 package First_Switches
is new Table
.Table
88 (Table_Component_Type
=> String_Access
,
89 Table_Index_Type
=> Integer,
92 Table_Increment
=> 100,
93 Table_Name
=> "Gnatcmd.First_Switches");
99 -- The switch tables contain an entry for each switch recognized by the
100 -- command processor. The syntax of entries is as follows:
102 -- SWITCH_STRING ::= "/ command-qualifier-name TRANSLATION"
105 -- DIRECT_TRANSLATION
106 -- | DIRECTORIES_TRANSLATION
107 -- | FILE_TRANSLATION
108 -- | NO_SPACE_FILE_TRANSL
109 -- | NUMERIC_TRANSLATION
110 -- | STRING_TRANSLATION
111 -- | OPTIONS_TRANSLATION
112 -- | COMMANDS_TRANSLATION
113 -- | ALPHANUMPLUS_TRANSLATION
114 -- | OTHER_TRANSLATION
116 -- DIRECT_TRANSLATION ::= space UNIX_SWITCHES
117 -- DIRECTORIES_TRANSLATION ::= =* UNIX_SWITCH *
118 -- DIRECTORY_TRANSLATION ::= =% UNIX_SWITCH %
119 -- FILE_TRANSLATION ::= =@ UNIX_SWITCH @
120 -- NO_SPACE_FILE_TRANSL ::= =< UNIX_SWITCH >
121 -- NUMERIC_TRANSLATION ::= =# UNIX_SWITCH # | # number #
122 -- STRING_TRANSLATION ::= =" UNIX_SWITCH "
123 -- OPTIONS_TRANSLATION ::= =OPTION {space OPTION}
124 -- COMMANDS_TRANSLATION ::= =? ARGS space command-name
125 -- ALPHANUMPLUS_TRANSLATION ::= =| UNIX_SWITCH |
127 -- UNIX_SWITCHES ::= UNIX_SWITCH {, UNIX_SWITCH}
129 -- UNIX_SWITCH ::= unix-switch-string | !unix-switch-string | `string'
131 -- OPTION ::= option-name space UNIX_SWITCHES
133 -- ARGS ::= -cargs | -bargs | -largs
135 -- Here command-qual is the name of the switch recognized by the GNATCmd.
136 -- This is always given in upper case in the templates, although in the
137 -- actual commands, either upper or lower case is allowed.
139 -- The unix-switch-string always starts with a minus, and has no commas
140 -- or spaces in it. Case is significant in the unix switch string. If a
141 -- unix switch string is preceded by the not sign (!) it means that the
142 -- effect of the corresponding command qualifer is to remove any previous
143 -- occurrence of the given switch in the command line.
145 -- The DIRECTORIES_TRANSLATION format is used where a list of directories
146 -- is given. This possible corresponding formats recognized by GNATCmd are
147 -- as shown by the following example for the case of PATH
150 -- PATH=(direc,direc,direc,direc)
152 -- When more than one directory is present for the DIRECTORIES case, then
153 -- multiple instances of the corresponding unix switch are generated,
154 -- with the file name being substituted for the occurrence of *.
156 -- The FILE_TRANSLATION format is similar except that only a single
157 -- file is allowed, not a list of files, and only one unix switch is
158 -- generated as a result.
160 -- the NO_SPACE_FILE_TRANSL is similar to FILE_TRANSLATION, except that
161 -- no space is inserted between the switch and the file name.
163 -- The NUMERIC_TRANSLATION format is similar to the FILE_TRANSLATION case
164 -- except that the parameter is a decimal integer in the range 0 to 999.
166 -- For the OPTIONS_TRANSLATION case, GNATCmd similarly permits one or
167 -- more options to appear (although only in some cases does the use of
168 -- multiple options make logical sense). For example, taking the
169 -- case of ERRORS for GCC, the following are all allowed:
172 -- /ERRORS=(FULL,VERBOSE)
173 -- /ERRORS=(BRIEF IMMEDIATE)
175 -- If no option is provided (e.g. just /ERRORS is written), then the
176 -- first option in the list is the default option. For /ERRORS this
177 -- is NORMAL, so /ERRORS with no option is equivalent to /ERRORS=NORMAL.
179 -- The COMMANDS_TRANSLATION case is only used for gnatmake, to correspond
180 -- to the use of -cargs, -bargs and -largs (the ARGS string as indicated
181 -- is one of these three possibilities). The name given by COMMAND is the
182 -- corresponding command name to be used to interprete the switches to be
183 -- passed on. Switches of this type set modes, e.g. /COMPILER_QUALIFIERS
184 -- sets the mode so that all subsequent switches, up to another switch
185 -- with COMMANDS_TRANSLATION apply to the corresponding commands issued
186 -- by the make utility. For example
188 -- /COMPILER_QUALIFIERS /LIST /BINDER_QUALIFIERS /MAIN
189 -- /COMPILER_QUALIFIERS /NOLIST /COMPILE_CHECKS=SYNTAX
191 -- Clearly these switches must come at the end of the list of switches
192 -- since all subsequent switches apply to an issued command.
194 -- For the DIRECT_TRANSLATION case, an implicit additional entry is
195 -- created by prepending NO to the name of the qualifer, and then
196 -- inverting the sense of the UNIX_SWITCHES string. For example,
201 -- An implicit entry is created:
205 -- In the case where, a ! is already present, inverting the sense of the
206 -- switch means removing it.
209 -- A synonym to shorten the table
211 type String_Ptr
is access constant String;
212 -- String pointer type used throughout
214 type Switches
is array (Natural range <>) of String_Ptr
;
215 -- Type used for array of swtiches
217 type Switches_Ptr
is access constant Switches
;
219 --------------------------------
220 -- Switches for project files --
221 --------------------------------
223 S_Ext_Ref
: aliased constant S
:= "/EXTERNAL_REFERENCE=" & '"' &
226 S_Project_File
: aliased constant S
:= "/PROJECT_FILE=<" &
228 S_Project_Verb
: aliased constant S
:= "/PROJECT_FILE_VERBOSITY=" &
236 ----------------------------
237 -- Switches for GNAT BIND --
238 ----------------------------
240 S_Bind_Bind
: aliased constant S
:= "/BIND_FILE=" &
246 S_Bind_Build
: aliased constant S
:= "/BUILD_LIBRARY=|" &
249 S_Bind_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
252 S_Bind_Debug
: aliased constant S
:= "/DEBUG=" &
268 S_Bind_DebugX
: aliased constant S
:= "/NODEBUG " &
271 S_Bind_Elab
: aliased constant S
:= "/ELABORATION_DEPENDENCIES " &
274 S_Bind_Error
: aliased constant S
:= "/ERROR_LIMIT=#" &
277 S_Bind_Help
: aliased constant S
:= "/HELP " &
280 S_Bind_Init
: aliased constant S
:= "/INITIALIZE_SCALARS=" &
288 S_Bind_Library
: aliased constant S
:= "/LIBRARY_SEARCH=*" &
291 S_Bind_Linker
: aliased constant S
:= "/LINKER_OPTION_LIST " &
294 S_Bind_List
: aliased constant S
:= "/LIST_RESTRICTIONS " &
297 S_Bind_Main
: aliased constant S
:= "/MAIN " &
300 S_Bind_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
303 S_Bind_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
306 S_Bind_No_Time
: aliased constant S
:= "/NO_TIME_STAMP_CHECK " &
309 S_Bind_Object
: aliased constant S
:= "/OBJECT_LIST " &
312 S_Bind_Order
: aliased constant S
:= "/ORDER_OF_ELABORATION " &
315 S_Bind_Output
: aliased constant S
:= "/OUTPUT=@" &
318 S_Bind_OutputX
: aliased constant S
:= "/NOOUTPUT " &
321 S_Bind_Pess
: aliased constant S
:= "/PESSIMISTIC_ELABORATION " &
324 S_Bind_Read
: aliased constant S
:= "/READ_SOURCES=" &
332 S_Bind_ReadX
: aliased constant S
:= "/NOREAD_SOURCES " &
335 S_Bind_Rename
: aliased constant S
:= "/RENAME_MAIN=<" &
338 S_Bind_Report
: aliased constant S
:= "/REPORT_ERRORS=" &
346 S_Bind_ReportX
: aliased constant S
:= "/NOREPORT_ERRORS " &
349 S_Bind_Restr
: aliased constant S
:= "/RESTRICTION_LIST " &
352 S_Bind_RTS
: aliased constant S
:= "/RUNTIME_SYSTEM=|" &
355 S_Bind_Search
: aliased constant S
:= "/SEARCH=*" &
358 S_Bind_Shared
: aliased constant S
:= "/SHARED " &
361 S_Bind_Slice
: aliased constant S
:= "/TIME_SLICE=#" &
364 S_Bind_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
367 S_Bind_Time
: aliased constant S
:= "/TIME_STAMP_CHECK " &
370 S_Bind_Verbose
: aliased constant S
:= "/VERBOSE " &
373 S_Bind_Warn
: aliased constant S
:= "/WARNINGS=" &
381 S_Bind_WarnX
: aliased constant S
:= "/NOWARNINGS " &
384 Bind_Switches
: aliased constant Switches
:=
385 (S_Bind_Bind
'Access,
386 S_Bind_Build 'Access,
387 S_Bind_Current
'Access,
388 S_Bind_Debug 'Access,
389 S_Bind_DebugX
'Access,
391 S_Bind_Error
'Access,
395 S_Bind_Library
'Access,
396 S_Bind_Linker 'Access,
399 S_Bind_Nostinc
'Access,
400 S_Bind_Nostlib 'Access,
401 S_Bind_No_Time
'Access,
402 S_Bind_Object 'Access,
403 S_Bind_Order
'Access,
404 S_Bind_Output 'Access,
405 S_Bind_OutputX
'Access,
407 S_Project_File
'Access,
408 S_Project_Verb 'Access,
410 S_Bind_ReadX 'Access,
411 S_Bind_Rename
'Access,
412 S_Bind_Report 'Access,
413 S_Bind_ReportX
'Access,
414 S_Bind_Restr 'Access,
416 S_Bind_Search 'Access,
417 S_Bind_Shared
'Access,
418 S_Bind_Slice 'Access,
419 S_Bind_Source
'Access,
421 S_Bind_Verbose
'Access,
423 S_Bind_WarnX
'Access);
425 ----------------------------
426 -- Switches for GNAT CHOP --
427 ----------------------------
429 S_Chop_Comp : aliased constant S := "/COMPILATION " &
432 S_Chop_File : aliased constant S := "/FILE_NAME_MAX_LENGTH=#" &
435 S_Chop_Help : aliased constant S := "/HELP " &
438 S_Chop_Over : aliased constant S := "/OVERWRITE " &
441 S_Chop_Pres : aliased constant S := "/PRESERVE " &
444 S_Chop_Quiet : aliased constant S := "/QUIET " &
447 S_Chop_Ref : aliased constant S := "/REFERENCE " &
450 S_Chop_Verb : aliased constant S := "/VERBOSE " &
453 Chop_Switches : aliased constant Switches :=
454 (S_Chop_Comp 'Access,
459 S_Chop_Quiet
'Access,
461 S_Chop_Verb
'Access);
463 -------------------------------
464 -- Switches for GNAT COMPILE --
465 -------------------------------
467 S_GCC_Ada_83 : aliased constant S := "/83 " &
470 S_GCC_Ada_95 : aliased constant S := "/95 " &
473 S_GCC_Asm : aliased constant S := "/ASM " &
476 S_GCC_Checks : aliased constant S := "/CHECKS=" &
478 "-gnato,!-gnatE,!-gnatp " &
490 S_GCC_ChecksX : aliased constant S := "/NOCHECKS " &
491 "-gnatp,!-gnato,!-gnatE";
493 S_GCC_Compres : aliased constant S := "/COMPRESS_NAMES " &
496 S_GCC_Config : aliased constant S := "/CONFIGURATION_PRAGMAS_FILE=<" &
499 S_GCC_Current : aliased constant S := "/CURRENT_DIRECTORY " &
502 S_GCC_Debug : aliased constant S := "/DEBUG=" &
516 S_GCC_DebugX : aliased constant S := "/NODEBUG " &
519 S_GCC_Dist : aliased constant S := "/DISTRIBUTION_STUBS=" &
525 S_GCC_DistX : aliased constant S := "/NODISTRIBUTION_STUBS " &
528 S_GCC_Error : aliased constant S := "/ERROR_LIMIT=#" &
531 S_GCC_ErrorX : aliased constant S := "/NOERROR_LIMIT " &
534 S_GCC_Expand : aliased constant S := "/EXPAND_SOURCE " &
537 S_GCC_Extend : aliased constant S := "/EXTENSIONS_ALLOWED " &
540 S_GCC_File : aliased constant S := "/FILE_NAME_MAX_LENGTH=#" &
543 S_GCC_Force : aliased constant S := "/FORCE_ALI " &
546 S_GCC_Help : aliased constant S := "/HELP " &
549 S_GCC_Ident : aliased constant S := "/IDENTIFIER_CHARACTER_SET=" &
573 S_GCC_IdentX : aliased constant S := "/NOIDENTIFIER_CHARACTER_SET " &
576 S_GCC_Immed : aliased constant S := "/IMMEDIATE_ERRORS " &
579 S_GCC_Inline : aliased constant S := "/INLINE=" &
587 S_GCC_InlineX : aliased constant S := "/NOINLINE " &
590 S_GCC_Jumps : aliased constant S := "/LONGJMP_SETJMP " &
593 S_GCC_Length : aliased constant S := "/MAX_LINE_LENGTH=#" &
596 S_GCC_List : aliased constant S := "/LIST " &
599 S_GCC_Noadc : aliased constant S := "/NO_GNAT_ADC " &
602 S_GCC_Noload : aliased constant S := "/NOLOAD " &
605 S_GCC_Nostinc : aliased constant S := "/NOSTD_INCLUDES " &
608 S_GCC_Opt : aliased constant S := "/OPTIMIZE=" &
610 "-O2,!-O0,!-O1,!-O3 " &
612 "-O0,!-O1,!-O2,!-O3 " &
614 "-O1,!-O0,!-O2,!-O3 " &
616 "-O1,!-O0,!-O2,!-O3 " &
620 "-O3,!-O0,!-O1,!-O2";
622 S_GCC_OptX : aliased constant S := "/NOOPTIMIZE " &
623 "-O0,!-O1,!-O2,!-O3";
625 S_GCC_Polling : aliased constant S := "/POLLING " &
628 S_GCC_Report : aliased constant S := "/REPORT_ERRORS=" &
640 S_GCC_ReportX : aliased constant S := "/NOREPORT_ERRORS " &
643 S_GCC_Repinfo : aliased constant S := "/REPRESENTATION_INFO=" &
655 S_GCC_RepinfX : aliased constant S := "/NOREPRESENTATION_INFO " &
658 S_GCC_Search : aliased constant S := "/SEARCH=*" &
661 S_GCC_Style : aliased constant S := "/STYLE_CHECKS=" &
706 "ORDERED_SUBPROGRAMS " &
712 "RM_COLUMN_LAYOUT " &
719 S_GCC_StyleX : aliased constant S := "/NOSTYLE_CHECKS " &
722 S_GCC_Syntax : aliased constant S := "/SYNTAX_ONLY " &
725 S_GCC_Trace : aliased constant S := "/TRACE_UNITS " &
728 S_GCC_Tree : aliased constant S := "/TREE_OUTPUT " &
731 S_GCC_Trys : aliased constant S := "/TRY_SEMANTICS " &
734 S_GCC_Units : aliased constant S := "/UNITS_LIST " &
737 S_GCC_Unique : aliased constant S := "/UNIQUE_ERROR_TAG " &
740 S_GCC_Upcase : aliased constant S := "/UPPERCASE_EXTERNALS " &
743 S_GCC_Valid : aliased constant S := "/VALIDITY_CHECKING=" &
785 S_GCC_Verbose : aliased constant S := "/VERBOSE " &
788 S_GCC_Warn : aliased constant S := "/WARNINGS=" &
790 "!-gnatws,!-gnatwe " &
795 "NOBIASED_ROUNDING " &
801 "IMPLICIT_DEREFERENCE " &
803 "NO_IMPLICIT_DEREFERENCE " &
817 "NOIMPLEMENTATION " &
819 "INEFFECTIVE_INLINE " &
821 "NOINEFFECTIVE_INLINE " &
839 "UNREFERENCED_FORMALS " &
841 "NOUNREFERENCED_FORMALS " &
848 S_GCC_WarnX : aliased constant S := "/NOWARNINGS " &
851 S_GCC_Wide : aliased constant S := "/WIDE_CHARACTER_ENCODING=" &
867 S_GCC_WideX : aliased constant S := "/NOWIDE_CHARACTER_ENCODING " &
870 S_GCC_Xdebug : aliased constant S := "/XDEBUG " &
873 S_GCC_Xref : aliased constant S := "/XREF=" &
879 GCC_Switches : aliased constant Switches :=
880 (S_GCC_Ada_83 'Access,
881 S_GCC_Ada_95
'Access,
883 S_GCC_Checks
'Access,
884 S_GCC_ChecksX 'Access,
885 S_GCC_Compres
'Access,
886 S_GCC_Config 'Access,
887 S_GCC_Current
'Access,
889 S_GCC_DebugX
'Access,
893 S_GCC_ErrorX
'Access,
894 S_GCC_Expand 'Access,
895 S_GCC_Extend
'Access,
901 S_GCC_IdentX
'Access,
903 S_GCC_Inline
'Access,
904 S_GCC_InlineX 'Access,
906 S_GCC_Length 'Access,
909 S_GCC_Noload
'Access,
910 S_GCC_Nostinc 'Access,
913 S_GCC_Polling
'Access,
914 S_Project_File'Access,
915 S_Project_Verb'Access,
916 S_GCC_Report 'Access,
917 S_GCC_ReportX
'Access,
918 S_GCC_Repinfo 'Access,
919 S_GCC_RepinfX
'Access,
920 S_GCC_Search 'Access,
922 S_GCC_StyleX 'Access,
923 S_GCC_Syntax
'Access,
928 S_GCC_Unique 'Access,
929 S_GCC_Upcase
'Access,
931 S_GCC_Verbose
'Access,
936 S_GCC_Xdebug 'Access,
939 ----------------------------
940 -- Switches for GNAT ELIM --
941 ----------------------------
943 S_Elim_All : aliased constant S := "/ALL " &
946 S_Elim_Bind : aliased constant S := "/BIND_FILE=<" &
949 S_Elim_Miss : aliased constant S := "/MISSED " &
952 S_Elim_Quiet : aliased constant S := "/QUIET " &
955 S_Elim_Tree : aliased constant S := "/TREE_DIRS=*" &
958 S_Elim_Verb : aliased constant S := "/VERBOSE " &
961 Elim_Switches : aliased constant Switches :=
965 S_Elim_Quiet
'Access,
967 S_Elim_Verb
'Access);
969 ----------------------------
970 -- Switches for GNAT FIND --
971 ----------------------------
973 S_Find_All : aliased constant S := "/ALL_FILES " &
976 S_Find_Deriv : aliased constant S := "/DERIVED_TYPE_INFORMATION " &
979 S_Find_Expr : aliased constant S := "/EXPRESSIONS " &
982 S_Find_Full : aliased constant S := "/FULL_PATHNAME " &
985 S_Find_Ignore : aliased constant S := "/IGNORE_LOCALS " &
988 S_Find_Nostinc : aliased constant S := "/NOSTD_INCLUDES " &
991 S_Find_Nostlib : aliased constant S := "/NOSTD_LIBRARIES " &
994 S_Find_Object : aliased constant S := "/OBJECT_SEARCH=*" &
997 S_Find_Print : aliased constant S := "/PRINT_LINES " &
1000 S_Find_Project : aliased constant S := "/PROJECT=@" &
1003 S_Find_Ref : aliased constant S := "/REFERENCES " &
1006 S_Find_Search : aliased constant S := "/SEARCH=*" &
1009 S_Find_Source : aliased constant S := "/SOURCE_SEARCH=*" &
1012 S_Find_Types : aliased constant S := "/TYPE_HIERARCHY " &
1015 Find_Switches : aliased constant Switches :=
1016 (S_Find_All 'Access,
1017 S_Find_Deriv
'Access,
1018 S_Find_Expr 'Access,
1020 S_Find_Full 'Access,
1021 S_Find_Ignore
'Access,
1022 S_Find_Nostinc 'Access,
1023 S_Find_Nostlib
'Access,
1024 S_Find_Object 'Access,
1025 S_Find_Print
'Access,
1026 S_Find_Project 'Access,
1027 S_Project_File
'Access,
1028 S_Project_Verb 'Access,
1030 S_Find_Search 'Access,
1031 S_Find_Source
'Access,
1032 S_Find_Types 'Access);
1034 ------------------------------
1035 -- Switches for GNAT KRUNCH --
1036 ------------------------------
1038 S_Krunch_Count
: aliased constant S
:= "/COUNT=#" &
1041 Krunch_Switches
: aliased constant Switches
:=
1042 (1 .. 1 => S_Krunch_Count
'Access);
1044 -------------------------------
1045 -- Switches for GNAT LIBRARY --
1046 -------------------------------
1048 S_Lbr_Config : aliased constant S := "/CONFIG=@" &
1051 S_Lbr_Create : aliased constant S := "/CREATE=%" &
1054 S_Lbr_Delete : aliased constant S := "/DELETE=%" &
1057 S_Lbr_Set : aliased constant S := "/SET=%" &
1060 Lbr_Switches : aliased constant Switches :=
1061 (S_Lbr_Config 'Access,
1062 S_Lbr_Create
'Access,
1063 S_Lbr_Delete 'Access,
1066 ----------------------------
1067 -- Switches for GNAT LINK --
1068 ----------------------------
1070 S_Link_Bind : aliased constant S := "/BIND_FILE=" &
1076 S_Link_Debug : aliased constant S := "/DEBUG=" &
1086 S_Link_Execut : aliased constant S := "/EXECUTABLE=@" &
1089 S_Link_Force : aliased constant S := "/FORCE_OBJECT_FILE_LIST " &
1092 S_Link_Ident : aliased constant S := "/IDENTIFICATION=" & '"' &
1093 "--for-linker=IDENT=" &
1096 S_Link_Nocomp
: aliased constant S
:= "/NOCOMPILE " &
1099 S_Link_Nofiles
: aliased constant S
:= "/NOSTART_FILES " &
1102 S_Link_Noinhib
: aliased constant S
:= "/NOINHIBIT-EXEC " &
1103 "--for-linker=--noinhibit-exec";
1105 S_Link_Static
: aliased constant S
:= "/STATIC " &
1106 "--for-linker=-static";
1108 S_Link_Verb
: aliased constant S
:= "/VERBOSE " &
1111 S_Link_ZZZZZ
: aliased constant S
:= "/<other> " &
1114 Link_Switches
: aliased constant Switches
:=
1115 (S_Link_Bind
'Access,
1116 S_Link_Debug 'Access,
1117 S_Link_Execut
'Access,
1119 S_Link_Force
'Access,
1120 S_Link_Ident 'Access,
1121 S_Link_Nocomp
'Access,
1122 S_Link_Nofiles 'Access,
1123 S_Link_Noinhib
'Access,
1124 S_Project_File 'Access,
1125 S_Project_Verb
'Access,
1126 S_Link_Static 'Access,
1127 S_Link_Verb
'Access,
1128 S_Link_ZZZZZ 'Access);
1130 ----------------------------
1131 -- Switches for GNAT LIST --
1132 ----------------------------
1134 S_List_All
: aliased constant S
:= "/ALL_UNITS " &
1137 S_List_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
1140 S_List_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1143 S_List_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1146 S_List_Output
: aliased constant S
:= "/OUTPUT=" &
1160 S_List_Search
: aliased constant S
:= "/SEARCH=*" &
1163 S_List_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1166 List_Switches
: aliased constant Switches
:=
1167 (S_List_All
'Access,
1168 S_List_Current 'Access,
1170 S_List_Nostinc 'Access,
1171 S_List_Object
'Access,
1172 S_List_Output 'Access,
1173 S_Project_File
'Access,
1174 S_Project_Verb 'Access,
1175 S_List_Search
'Access,
1176 S_List_Source 'Access);
1178 ----------------------------
1179 -- Switches for GNAT MAKE --
1180 ----------------------------
1182 S_Make_Actions
: aliased constant S
:= "/ACTIONS=" &
1190 S_Make_All
: aliased constant S
:= "/ALL_FILES " &
1193 S_Make_Bind
: aliased constant S
:= "/BINDER_QUALIFIERS=?" &
1196 S_Make_Comp
: aliased constant S
:= "/COMPILER_QUALIFIERS=?" &
1199 S_Make_Cond
: aliased constant S
:= "/CONDITIONAL_SOURCE_SEARCH=*" &
1202 S_Make_Cont
: aliased constant S
:= "/CONTINUE_ON_ERROR " &
1205 S_Make_Current
: aliased constant S
:= "/CURRENT_DIRECTORY " &
1208 S_Make_Dep
: aliased constant S
:= "/DEPENDENCIES_LIST " &
1211 S_Make_Doobj
: aliased constant S
:= "/DO_OBJECT_CHECK " &
1214 S_Make_Execut
: aliased constant S
:= "/EXECUTABLE=@" &
1217 S_Make_Force
: aliased constant S
:= "/FORCE_COMPILE " &
1220 S_Make_Inplace
: aliased constant S
:= "/IN_PLACE " &
1223 S_Make_Library
: aliased constant S
:= "/LIBRARY_SEARCH=*" &
1226 S_Make_Link
: aliased constant S
:= "/LINKER_QUALIFIERS=?" &
1229 S_Make_Mapping
: aliased constant S
:= "/MAPPING " &
1232 S_Make_Minimal
: aliased constant S
:= "/MINIMAL_RECOMPILATION " &
1235 S_Make_Nolink
: aliased constant S
:= "/NOLINK " &
1238 S_Make_Nomain
: aliased constant S
:= "/NOMAIN " &
1241 S_Make_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1244 S_Make_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
1247 S_Make_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1250 S_Make_Proc
: aliased constant S
:= "/PROCESSES=#" &
1253 S_Make_Nojobs
: aliased constant S
:= "/NOPROCESSES " &
1256 S_Make_Quiet
: aliased constant S
:= "/QUIET " &
1259 S_Make_Reason
: aliased constant S
:= "/REASONS " &
1262 S_Make_RTS
: aliased constant S
:= "/RUNTIME_SYSTEM=|" &
1265 S_Make_Search
: aliased constant S
:= "/SEARCH=*" &
1268 S_Make_Skip
: aliased constant S
:= "/SKIP_MISSING=*" &
1271 S_Make_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1274 S_Make_Switch
: aliased constant S
:= "/SWITCH_CHECK " &
1277 S_Make_Unique
: aliased constant S
:= "/UNIQUE " &
1280 S_Make_Verbose
: aliased constant S
:= "/VERBOSE " &
1283 Make_Switches
: aliased constant Switches
:=
1284 (S_Make_Actions
'Access,
1286 S_Make_Bind
'Access,
1287 S_Make_Comp 'Access,
1288 S_Make_Cond
'Access,
1289 S_Make_Cont 'Access,
1290 S_Make_Current
'Access,
1292 S_Make_Doobj
'Access,
1293 S_Make_Execut 'Access,
1295 S_Make_Force 'Access,
1296 S_Make_Inplace
'Access,
1297 S_Make_Library 'Access,
1298 S_Make_Link
'Access,
1299 S_Make_Mapping 'Access,
1300 S_Make_Minimal
'Access,
1301 S_Make_Nolink 'Access,
1302 S_Make_Nomain
'Access,
1303 S_Make_Nostinc 'Access,
1304 S_Make_Nostlib
'Access,
1305 S_Make_Object 'Access,
1306 S_Make_Proc
'Access,
1307 S_Project_File 'Access,
1308 S_Project_Verb
'Access,
1309 S_Make_Nojobs 'Access,
1310 S_Make_Quiet
'Access,
1311 S_Make_Reason 'Access,
1313 S_Make_Search 'Access,
1314 S_Make_Skip
'Access,
1315 S_Make_Source 'Access,
1316 S_Make_Switch
'Access,
1317 S_Make_Unique 'Access,
1318 S_Make_Verbose
'Access);
1320 ----------------------------
1321 -- Switches for GNAT Name --
1322 ----------------------------
1324 S_Name_Conf : aliased constant S := "/CONFIG_FILE=<" &
1327 S_Name_Dirs : aliased constant S := "/SOURCE_DIRS=*" &
1330 S_Name_Dfile : aliased constant S := "/DIRS_FILE=<" &
1333 S_Name_Help : aliased constant S := "/HELP" &
1336 S_Name_Proj : aliased constant S := "/PROJECT_FILE=<" &
1339 S_Name_Verbose : aliased constant S := "/VERBOSE" &
1342 Name_Switches : aliased constant Switches :=
1343 (S_Name_Conf 'Access,
1344 S_Name_Dirs
'Access,
1345 S_Name_Dfile 'Access,
1346 S_Name_Help
'Access,
1347 S_Name_Proj 'Access,
1348 S_Name_Verbose
'Access);
1350 ----------------------------------
1351 -- Switches for GNAT PREPROCESS --
1352 ----------------------------------
1354 S_Prep_Assoc : aliased constant S := "/ASSOCIATE=" & '"' &
1357 S_Prep_Blank : aliased constant S := "/BLANK_LINES " &
1360 S_Prep_Com : aliased constant S := "/COMMENTS " &
1363 S_Prep_Ref : aliased constant S := "/REFERENCE " &
1366 S_Prep_Remove : aliased constant S := "/REMOVE " &
1369 S_Prep_Symbols : aliased constant S := "/SYMBOLS " &
1372 S_Prep_Undef : aliased constant S := "/UNDEFINED " &
1375 Prep_Switches : aliased constant Switches :=
1376 (S_Prep_Assoc 'Access,
1377 S_Prep_Blank
'Access,
1380 S_Prep_Remove 'Access,
1381 S_Prep_Symbols
'Access,
1382 S_Prep_Undef 'Access);
1384 ------------------------------
1385 -- Switches for GNAT SHARED --
1386 ------------------------------
1388 S_Shared_Debug
: aliased constant S
:= "/DEBUG=" &
1398 S_Shared_Image
: aliased constant S
:= "/IMAGE=@" &
1401 S_Shared_Ident
: aliased constant S
:= "/IDENTIFICATION=" & '"' &
1402 "--for-linker=IDENT=" &
1405 S_Shared_Nofiles
: aliased constant S
:= "/NOSTART_FILES " &
1408 S_Shared_Noinhib
: aliased constant S
:= "/NOINHIBIT-IMAGE " &
1409 "--for-linker=--noinhibit-exec";
1411 S_Shared_Verb
: aliased constant S
:= "/VERBOSE " &
1414 S_Shared_ZZZZZ
: aliased constant S
:= "/<other> " &
1417 Shared_Switches
: aliased constant Switches
:=
1418 (S_Shared_Debug
'Access,
1419 S_Shared_Image 'Access,
1420 S_Shared_Ident
'Access,
1421 S_Shared_Nofiles 'Access,
1422 S_Shared_Noinhib
'Access,
1423 S_Shared_Verb 'Access,
1424 S_Shared_ZZZZZ
'Access);
1426 --------------------------------
1427 -- Switches for GNAT STANDARD --
1428 --------------------------------
1430 Standard_Switches : aliased constant Switches := (1 .. 0 => null);
1432 ----------------------------
1433 -- Switches for GNAT STUB --
1434 ----------------------------
1436 S_Stub_Current : aliased constant S := "/CURRENT_DIRECTORY " &
1439 S_Stub_Full : aliased constant S := "/FULL " &
1442 S_Stub_Header : aliased constant S := "/HEADER=" &
1448 S_Stub_Indent : aliased constant S := "/INDENTATION=#" &
1451 S_Stub_Length : aliased constant S := "/LINE_LENGTH=#" &
1454 S_Stub_Quiet : aliased constant S := "/QUIET " &
1457 S_Stub_Search : aliased constant S := "/SEARCH=*" &
1460 S_Stub_Tree : aliased constant S := "/TREE_FILE=" &
1468 S_Stub_Verbose : aliased constant S := "/VERBOSE " &
1471 Stub_Switches : aliased constant Switches :=
1472 (S_Stub_Current 'Access,
1473 S_Stub_Full
'Access,
1474 S_Stub_Header 'Access,
1475 S_Stub_Indent
'Access,
1476 S_Stub_Length 'Access,
1477 S_Stub_Quiet
'Access,
1478 S_Stub_Search 'Access,
1479 S_Stub_Tree
'Access,
1480 S_Stub_Verbose 'Access);
1482 ----------------------------
1483 -- Switches for GNAT XREF --
1484 ----------------------------
1486 S_Xref_All
: aliased constant S
:= "/ALL_FILES " &
1489 S_Xref_Deriv
: aliased constant S
:= "/DERIVED_TYPES " &
1492 S_Xref_Full
: aliased constant S
:= "/FULL_PATHNAME " &
1495 S_Xref_Global
: aliased constant S
:= "/IGNORE_LOCALS " &
1498 S_Xref_Nostinc
: aliased constant S
:= "/NOSTD_INCLUDES " &
1501 S_Xref_Nostlib
: aliased constant S
:= "/NOSTD_LIBRARIES " &
1504 S_Xref_Object
: aliased constant S
:= "/OBJECT_SEARCH=*" &
1507 S_Xref_Project
: aliased constant S
:= "/PROJECT=@" &
1510 S_Xref_Search
: aliased constant S
:= "/SEARCH=*" &
1513 S_Xref_Source
: aliased constant S
:= "/SOURCE_SEARCH=*" &
1516 S_Xref_Output
: aliased constant S
:= "/UNUSED " &
1519 S_Xref_Tags
: aliased constant S
:= "/TAGS " &
1522 Xref_Switches
: aliased constant Switches
:=
1523 (S_Xref_All
'Access,
1524 S_Xref_Deriv 'Access,
1526 S_Xref_Full 'Access,
1527 S_Xref_Global
'Access,
1528 S_Xref_Nostinc 'Access,
1529 S_Xref_Nostlib
'Access,
1530 S_Xref_Object 'Access,
1531 S_Xref_Project
'Access,
1532 S_Project_File 'Access,
1533 S_Project_Verb
'Access,
1534 S_Xref_Search 'Access,
1535 S_Xref_Source
'Access,
1536 S_Xref_Output 'Access,
1537 S_Xref_Tags
'Access);
1543 -- The command table contains an entry for each command recognized by
1544 -- GNATCmd. The entries are represented by an array of records.
1546 type Parameter_Type is
1547 -- A parameter is defined as a whitespace bounded string, not begining
1548 -- with a slash. (But see note under FILES_OR_WILDCARD).
1550 -- A required file or directory parameter.
1553 -- An optional file or directory parameter.
1556 -- A parameter that's passed through as is (not canonicalized)
1559 -- An unlimited number of whitespace separate file or directory
1560 -- parameters including wildcard specifications.
1563 -- Un unlimited number of whitespace separated paameters that are
1564 -- passed through as is (not canonicalized).
1567 -- A comma separated list of files and/or wildcard file specifications.
1568 -- A comma preceded by or followed by whitespace is considered as a
1569 -- single comma character w/o whitespace.
1571 type Parameter_Array is array (Natural range <>) of Parameter_Type;
1572 type Parameter_Ref is access all Parameter_Array;
1574 type Command_Type is
1575 (Bind, Chop, Compile, Elim, Find, Krunch, Library, Link, List,
1576 Make, Name, Preprocess, Shared, Standard, Stub, Xref, Undefined);
1578 type Alternate_Command is (Comp, Ls, Kr, Prep, Psta);
1579 -- Alternate command libel for non VMS system
1581 Corresponding_To : constant array (Alternate_Command) of Command_Type :=
1587 -- Mapping of alternate commands to commands
1589 subtype Real_Command_Type is Command_Type range Bind .. Xref;
1591 type Command_Entry is record
1593 -- Command name for GNAT xxx command
1596 -- A usage string, used for error messages
1598 Unixcmd : String_Ptr;
1599 -- Corresponding Unix command
1601 Unixsws : Argument_List_Access;
1602 -- Switches for the Unix command
1605 -- When True, the command can only be used on VMS
1607 Switches : Switches_Ptr;
1608 -- Pointer to array of switch strings
1610 Params : Parameter_Ref;
1611 -- Describes the allowable types of parameters.
1612 -- Params (1) is the type of the first parameter, etc.
1613 -- An empty parameter array means this command takes no parameters.
1615 Defext : String (1 .. 3);
1616 -- Default extension. If non-blank, then this extension is supplied by
1617 -- default as the extension for any file parameter which does not have
1618 -- an extension already.
1621 -------------------------
1622 -- INTERNAL STRUCTURES --
1623 -------------------------
1625 -- The switches and commands are defined by strings in the previous
1626 -- section so that they are easy to modify, but internally, they are
1627 -- kept in a more conveniently accessible form described in this
1630 -- Commands, command qualifers and options have a similar common format
1631 -- so that searching for matching names can be done in a common manner.
1633 type Item_Id is (Id_Command, Id_Switch, Id_Option);
1635 type Translation_Type is
1638 -- A qualifier with no options.
1639 -- Example: GNAT MAKE /VERBOSE
1642 -- A qualifier followed by a list of directories
1643 -- Example: GNAT COMPILE /SEARCH=([], [.FOO], [.BAR])
1646 -- A qualifier followed by one directory
1647 -- Example: GNAT LIBRARY /SET=[.VAXFLOATLIB]
1650 -- A qualifier followed by a filename
1651 -- Example: GNAT LINK /EXECUTABLE=FOO.EXE
1654 -- A qualifier followed by a filename
1655 -- Example: GNAT MAKE /PROJECT_FILE=PRJ.GPR
1658 -- A qualifier followed by a numeric value.
1659 -- Example: GNAT CHOP /FILE_NAME_MAX_LENGTH=39
1662 -- A qualifier followed by a quoted string. Only used by
1663 -- /IDENTIFICATION qualfier.
1664 -- Example: GNAT LINK /IDENTIFICATION="3.14a1 version"
1667 -- A qualifier followed by a list of options.
1668 -- Example: GNAT COMPILE /REPRESENTATION_INFO=(ARRAYS,OBJECTS)
1671 -- A qualifier followed by a list. Only used for
1672 -- MAKE /COMPILER_QUALIFIERS /BINDER_QUALIFIERS /LINKER_QUALIFIERS
1673 -- (gnatmake -cargs -bargs -largs )
1674 -- Example: GNAT MAKE ... /LINKER_QUALIFIERS /VERBOSE FOOBAR.OBJ
1677 -- A qualifier passed directly to the linker. Only used
1678 -- for LINK and SHARED if no other match is found.
1679 -- Example: GNAT LINK FOO.ALI /SYSSHR
1682 -- A qualifier followed by a legal linker symbol prefix. Only used
1683 -- for BIND /BUILD_LIBRARY (gnatbind -Lxyz).
1684 -- Example: GNAT BIND /BUILD_LIBRARY=foobar
1687 type Item (Id : Item_Id);
1688 type Item_Ptr is access all Item;
1690 type Item (Id : Item_Id) is record
1692 -- Name of the command, switch (with slash) or option
1695 -- Pointer to next item on list, always has the same Id value
1697 Command : Command_Type := Undefined;
1699 Unix_String : String_Ptr := null;
1700 -- Corresponding Unix string. For a command, this is the unix command
1701 -- name and possible default switches. For a switch or option it is
1702 -- the unix switch string.
1708 Switches : Item_Ptr;
1709 -- Pointer to list of switch items for the command, linked
1710 -- through the Next fields with null terminating the list.
1713 -- Usage information, used only for errors and the default
1714 -- list of commands output.
1716 Params : Parameter_Ref;
1717 -- Array of parameters
1719 Defext : String (1 .. 3);
1720 -- Default extension. If non-blank, then this extension is
1721 -- supplied by default as the extension for any file parameter
1722 -- which does not have an extension already.
1726 Translation : Translation_Type;
1727 -- Type of switch translation. For all cases, except Options,
1728 -- this is the only field needed, since the Unix translation
1729 -- is found in Unix_String.
1732 -- For the Options case, this field is set to point to a list
1733 -- of options item (for this case Unix_String is null in the
1734 -- main switch item). The end of the list is marked by null.
1739 -- No special fields needed, since Name and Unix_String are
1740 -- sufficient to completely described an option.
1745 subtype Command_Item is Item (Id_Command);
1746 subtype Switch_Item is Item (Id_Switch);
1747 subtype Option_Item is Item (Id_Option);
1749 ----------------------------------
1750 -- Declarations for GNATCMD use --
1751 ----------------------------------
1753 Commands : Item_Ptr;
1754 -- Pointer to head of list of command items, one for each command, with
1755 -- the end of the list marked by a null pointer.
1757 Last_Command : Item_Ptr;
1758 -- Pointer to last item in Commands list
1760 Normal_Exit : exception;
1761 -- Raise this exception for normal program termination
1763 Error_Exit : exception;
1764 -- Raise this exception if error detected
1766 Errors : Natural := 0;
1767 -- Count errors detected
1769 Command_Arg : Positive := 1;
1772 -- Pointer to command item for current command
1774 Make_Commands_Active : Item_Ptr := null;
1775 -- Set to point to Command entry for COMPILE, BIND, or LINK as appropriate
1776 -- if a COMMANDS_TRANSLATION switch has been encountered while processing
1779 My_Exit_Status : Exit_Status := Success;
1781 package Buffer is new Table.Table
1782 (Table_Component_Type => Character,
1783 Table_Index_Type => Integer,
1784 Table_Low_Bound => 1,
1785 Table_Initial => 4096,
1786 Table_Increment => 2,
1787 Table_Name => "Buffer");
1789 Param_Count : Natural := 0;
1790 -- Number of parameter arguments so far
1795 Display_Command : Boolean := False;
1796 -- Set true if /? switch causes display of generated command (on VMS)
1798 The_Command : Command_Type;
1801 -----------------------
1802 -- Local Subprograms --
1803 -----------------------
1805 function Index (Char : Character; Str : String) return Natural;
1806 -- Returns the first occurrence of Char in Str.
1807 -- Returns 0 if Char is not in Str.
1809 function Init_Object_Dirs return Argument_List;
1811 function Invert_Sense (S : String) return String_Ptr;
1812 -- Given a unix switch string S, computes the inverse (adding or
1813 -- removing ! characters as required), and returns a pointer to
1814 -- the allocated result on the heap.
1816 function Is_Extensionless (F : String) return Boolean;
1817 -- Returns true if the filename has no extension.
1819 function Match (S1, S2 : String) return Boolean;
1820 -- Determines whether S1 and S2 match. This is a case insensitive match.
1822 function Match_Prefix (S1, S2 : String) return Boolean;
1823 -- Determines whether S1 matches a prefix of S2. This is also a case
1824 -- insensitive match (for example Match ("AB","abc") is True).
1826 function Matching_Name
1829 Quiet : Boolean := False)
1831 -- Determines if the item list headed by Itm and threaded through the
1832 -- Next fields (with null marking the end of the list), contains an
1833 -- entry that uniquely matches the given string. The match is case
1834 -- insensitive and permits unique abbreviation. If the match succeeds,
1835 -- then a pointer to the matching item is returned. Otherwise, an
1836 -- appropriate error message is written. Note that the discriminant
1837 -- of Itm is used to determine the appropriate form of this message.
1838 -- Quiet is normally False as shown, if it is set to True, then no
1839 -- error message is generated in a not found situation (null is still
1840 -- returned to indicate the not-found situation).
1842 procedure Non_VMS_Usage;
1843 -- Display usage for platforms other than VMS
1845 function OK_Alphanumerplus (S : String) return Boolean;
1846 -- Checks that S is a string of alphanumeric characters,
1847 -- returning True if all alphanumeric characters,
1848 -- False if empty or a non-alphanumeric character is present.
1850 function OK_Integer (S : String) return Boolean;
1851 -- Checks that S is a string of digits, returning True if all digits,
1852 -- False if empty or a non-digit is present.
1854 procedure Output_Version;
1855 -- Output the version of this program
1857 procedure Place (C : Character);
1858 -- Place a single character in the buffer, updating Ptr
1860 procedure Place (S : String);
1861 -- Place a string character in the buffer, updating Ptr
1863 procedure Place_Lower (S : String);
1864 -- Place string in buffer, forcing letters to lower case, updating Ptr
1866 procedure Place_Unix_Switches (S : String_Ptr);
1867 -- Given a unix switch string, place corresponding switches in Buffer,
1868 -- updating Ptr appropriatelly. Note that in the case of use of ! the
1869 -- result may be to remove a previously placed switch.
1871 procedure Set_Library_For
1872 (Project : Project_Id;
1873 There_Are_Libraries : in out Boolean);
1874 -- If Project is a library project, add the correct
1875 -- -L and -l switches to the linker invocation.
1877 procedure Set_Libraries is
1878 new For_Every_Project_Imported (Boolean, Set_Library_For);
1879 -- Add the -L and -l switches to the linker for all
1880 -- of the library projects.
1882 procedure Validate_Command_Or_Option (N : String_Ptr);
1883 -- Check that N is a valid command or option name, i.e. that it is of the
1884 -- form of an Ada identifier with upper case letters and underscores.
1886 procedure Validate_Unix_Switch (S : String_Ptr);
1887 -- Check that S is a valid switch string as described in the syntax for
1888 -- the switch table item UNIX_SWITCH or else begins with a backquote.
1890 procedure VMS_Conversion (The_Command : out Command_Type);
1891 -- Converts VMS command line to equivalent Unix command line
1897 function Index (Char : Character; Str : String) return Natural is
1899 for Index in Str'Range loop
1900 if Str (Index) = Char then
1908 ----------------------
1909 -- Init_Object_Dirs --
1910 ----------------------
1912 function Init_Object_Dirs return Argument_List is
1913 Object_Dirs : Integer;
1914 Object_Dir : Argument_List (1 .. 256);
1915 Object_Dir_Name : String_Access;
1919 Object_Dir_Name := String_Access (Object_Dir_Default_Name);
1920 Get_Next_Dir_In_Path_Init (Object_Dir_Name);
1924 Dir : String_Access := String_Access
1925 (Get_Next_Dir_In_Path (Object_Dir_Name));
1927 exit when Dir = null;
1928 Object_Dirs := Object_Dirs + 1;
1929 Object_Dir (Object_Dirs) :=
1931 To_Canonical_Dir_Spec
1933 (Normalize_Directory_Name
(Dir
.all).all,
1934 True).all, True).all);
1938 Object_Dirs
:= Object_Dirs
+ 1;
1939 Object_Dir
(Object_Dirs
) := new String'("-lgnat");
1941 if Hostparm.OpenVMS then
1942 Object_Dirs := Object_Dirs + 1;
1943 Object_Dir (Object_Dirs) := new String'("-ldecgnat");
1946 return Object_Dir
(1 .. Object_Dirs
);
1947 end Init_Object_Dirs
;
1953 function Invert_Sense
(S
: String) return String_Ptr
is
1954 Sinv
: String (1 .. S
'Length * 2);
1955 -- Result (for sure long enough)
1957 Sinvp
: Natural := 0;
1958 -- Pointer to output string
1961 for Sp
in S
'Range loop
1962 if Sp
= S
'First or else S
(Sp
- 1) = ',' then
1963 if S
(Sp
) = '!' then
1966 Sinv
(Sinvp
+ 1) := '!';
1967 Sinv
(Sinvp
+ 2) := S
(Sp
);
1972 Sinv
(Sinvp
+ 1) := S
(Sp
);
1977 return new String'(Sinv (1 .. Sinvp));
1980 ----------------------
1981 -- Is_Extensionless --
1982 ----------------------
1984 function Is_Extensionless (F : String) return Boolean is
1986 for J in reverse F'Range loop
1989 elsif F (J) = '/' or else F (J) = ']' or else F (J) = ':' then
1995 end Is_Extensionless;
2001 function Match (S1, S2 : String) return Boolean is
2002 Dif : constant Integer := S2'First - S1'First;
2006 if S1'Length /= S2'Length then
2010 for J in S1'Range loop
2011 if To_Lower (S1 (J)) /= To_Lower (S2 (J + Dif)) then
2024 function Match_Prefix (S1, S2 : String) return Boolean is
2026 if S1'Length > S2'Length then
2029 return Match (S1, S2 (S2'First .. S2'First + S1'Length - 1));
2037 function Matching_Name
2040 Quiet : Boolean := False)
2046 -- Little procedure to output command/qualifier/option as appropriate
2047 -- and bump error count.
2059 Errors := Errors + 1;
2064 Put (Standard_Error, "command");
2068 Put (Standard_Error, "qualifier");
2070 Put (Standard_Error, "switch");
2074 Put (Standard_Error, "option");
2078 Put (Standard_Error, "input");
2082 Put (Standard_Error, ": ");
2083 Put (Standard_Error, S);
2086 -- Start of processing for Matching_Name
2089 -- If exact match, that's the one we want
2092 while P1 /= null loop
2093 if Match (S, P1.Name.all) then
2100 -- Now check for prefix matches
2103 while P1 /= null loop
2104 if P1.Name.all = "/<other>" then
2107 elsif not Match_Prefix (S, P1.Name.all) then
2111 -- Here we have found one matching prefix, so see if there is
2112 -- another one (which is an ambiguity)
2115 while P2 /= null loop
2116 if Match_Prefix (S, P2.Name.all) then
2118 Put (Standard_Error, "ambiguous ");
2120 Put (Standard_Error, " (matches ");
2121 Put (Standard_Error, P1.Name.all);
2123 while P2 /= null loop
2124 if Match_Prefix (S, P2.Name.all) then
2125 Put (Standard_Error, ',');
2126 Put (Standard_Error, P2.Name.all);
2132 Put_Line (Standard_Error, ")");
2141 -- If we fall through that loop, then there was only one match
2147 -- If we fall through outer loop, there was no match
2150 Put (Standard_Error, "unrecognized ");
2152 New_Line (Standard_Error);
2158 -----------------------
2159 -- OK_Alphanumerplus --
2160 -----------------------
2162 function OK_Alphanumerplus (S : String) return Boolean is
2164 if S'Length = 0 then
2168 for J in S'Range loop
2169 if not (Is_Alphanumeric (S (J)) or else
2170 S (J) = '_
' or else S (J) = '$
')
2178 end OK_Alphanumerplus;
2184 function OK_Integer (S : String) return Boolean is
2186 if S'Length = 0 then
2190 for J in S'Range loop
2191 if not Is_Digit (S (J)) then
2200 --------------------
2201 -- Output_Version --
2202 --------------------
2204 procedure Output_Version is
2207 Put (Gnatvsn.Gnat_Version_String);
2208 Put_Line (" Copyright 1996-2002 Free Software Foundation, Inc.");
2215 procedure Place (C : Character) is
2217 Buffer.Increment_Last;
2218 Buffer.Table (Buffer.Last) := C;
2220 -- Do not put a space as the first character in the buffer
2221 if C = ' ' and then Buffer.Last = 1 then
2222 Buffer.Decrement_Last;
2226 procedure Place (S : String) is
2228 for J in S'Range loop
2237 procedure Place_Lower (S : String) is
2239 for J in S'Range loop
2240 Place (To_Lower (S (J)));
2244 -------------------------
2245 -- Place_Unix_Switches --
2246 -------------------------
2248 procedure Place_Unix_Switches (S : String_Ptr) is
2249 P1, P2, P3 : Natural;
2255 while P1 <= S'Last loop
2256 if S (P1) = '!' then
2264 pragma Assert (S (P1) = '-' or else S (P1) = '`
');
2266 while P2 < S'Last and then S (P2 + 1) /= ',' loop
2270 -- Switch is now in S (P1 .. P2)
2272 Slen := P2 - P1 + 1;
2276 while P3 <= Buffer.Last - Slen loop
2277 if Buffer.Table (P3) = ' '
2278 and then String (Buffer.Table (P3 + 1 .. P3 + Slen)) =
2280 and then (P3 + Slen = Buffer.Last
2282 Buffer.Table (P3 + Slen + 1) = ' ')
2284 Buffer.Table (P3 .. Buffer.Last - Slen - 1) :=
2285 Buffer.Table (P3 + Slen + 1 .. Buffer.Last);
2286 Buffer.Set_Last (Buffer.Last - Slen - 1);
2296 if S (P1) = '`
' then
2300 Place (S (P1 .. P2));
2305 end Place_Unix_Switches;
2307 ---------------------
2308 -- Set_Library_For --
2309 ---------------------
2311 procedure Set_Library_For
2312 (Project : Project_Id;
2313 There_Are_Libraries : in out Boolean)
2316 -- Case of library project
2318 if Projects.Table (Project).Library then
2319 There_Are_Libraries := True;
2321 -- Add the -L switch
2323 Last_Switches.Increment_Last;
2324 Last_Switches.Table (Last_Switches.Last) :=
2327 (Projects
.Table
(Project
).Library_Dir
));
2329 -- Add the -l switch
2331 Last_Switches
.Increment_Last
;
2332 Last_Switches
.Table
(Last_Switches
.Last
) :=
2335 (Projects.Table (Project).Library_Name));
2337 -- Add the Wl,-rpath switch if library non static
2339 if Projects.Table (Project).Library_Kind /= Static then
2341 Option : constant String_Access :=
2342 MLib.Tgt.Linker_Library_Path_Option
2344 (Projects.Table (Project).Library_Dir));
2347 if Option /= null then
2348 Last_Switches.Increment_Last;
2349 Last_Switches.Table (Last_Switches.Last) :=
2358 end Set_Library_For;
2360 --------------------------------
2361 -- Validate_Command_Or_Option --
2362 --------------------------------
2364 procedure Validate_Command_Or_Option (N : String_Ptr) is
2366 pragma Assert (N'Length > 0);
2368 for J in N'Range loop
2370 pragma Assert (N (J - 1) /= '_
');
2373 pragma Assert (Is_Upper (N (J)) or else Is_Digit (N (J)));
2377 end Validate_Command_Or_Option;
2379 --------------------------
2380 -- Validate_Unix_Switch --
2381 --------------------------
2383 procedure Validate_Unix_Switch (S : String_Ptr) is
2385 if S (S'First) = '`
' then
2389 pragma Assert (S (S'First) = '-' or else S (S'First) = '!');
2391 for J in S'First + 1 .. S'Last loop
2392 pragma Assert (S (J) /= ' ');
2395 pragma Assert (S (J - 1) = ',' and then S (J + 1) = '-');
2399 end Validate_Unix_Switch;
2401 ----------------------
2402 -- List of Commands --
2403 ----------------------
2405 -- Note that we put this after all the local bodies (except Non_VMS_Usage
2406 -- and VMS_Conversion that use Command_List) to avoid some access before
2407 -- elaboration problems.
2409 Command_List : constant array (Real_Command_Type) of Command_Entry :=
2411 (Cname => new S'("BIND"),
2412 Usage
=> new S
'("GNAT BIND file[.ali] /qualifiers"),
2414 Unixcmd => new S'("gnatbind"),
2416 Switches
=> Bind_Switches
'Access,
2417 Params
=> new Parameter_Array
'(1 => File),
2421 (Cname => new S'("CHOP"),
2422 Usage
=> new S
'("GNAT CHOP file [directory] /qualifiers"),
2424 Unixcmd => new S'("gnatchop"),
2426 Switches
=> Chop_Switches
'Access,
2427 Params
=> new Parameter_Array
'(1 => File, 2 => Optional_File),
2431 (Cname => new S'("COMPILE"),
2432 Usage
=> new S
'("GNAT COMPILE filespec[,...] /qualifiers"),
2434 Unixcmd => new S'("gnatmake"),
2435 Unixsws
=> new Argument_List
' (1 => new String'("-f"),
2436 2 => new String'("-u"),
2437 3 => new String'("-c")),
2438 Switches
=> GCC_Switches
'Access,
2439 Params
=> new Parameter_Array
'(1 => Files_Or_Wildcard),
2443 (Cname => new S'("ELIM"),
2444 Usage
=> new S
'("GNAT ELIM name /qualifiers"),
2446 Unixcmd => new S'("gnatelim"),
2448 Switches
=> Elim_Switches
'Access,
2449 Params
=> new Parameter_Array
'(1 => Other_As_Is),
2453 (Cname => new S'("FIND"),
2454 Usage
=> new S
'("GNAT FIND pattern[:sourcefile[:line"
2455 & "[:column]]] filespec[,...] /qualifiers"),
2457 Unixcmd => new S'("gnatfind"),
2459 Switches
=> Find_Switches
'Access,
2460 Params
=> new Parameter_Array
'(1 => Other_As_Is,
2461 2 => Files_Or_Wildcard),
2465 (Cname => new S'("KRUNCH"),
2466 Usage
=> new S
'("GNAT KRUNCH file [/COUNT=nnn]"),
2468 Unixcmd => new S'("gnatkr"),
2470 Switches
=> Krunch_Switches
'Access,
2471 Params
=> new Parameter_Array
'(1 => File),
2475 (Cname => new S'("LIBRARY"),
2476 Usage
=> new S
'("GNAT LIBRARY /[CREATE | SET | DELETE]"
2477 & "=directory [/CONFIG=file]"),
2479 Unixcmd => new S'("gnatlbr"),
2481 Switches
=> Lbr_Switches
'Access,
2482 Params
=> new Parameter_Array
'(1 .. 0 => File),
2486 (Cname => new S'("LINK"),
2487 Usage
=> new S
'("GNAT LINK file[.ali]"
2488 & " [extra obj_&_lib_&_exe_&_opt files]"
2491 Unixcmd => new S'("gnatlink"),
2493 Switches
=> Link_Switches
'Access,
2494 Params
=> new Parameter_Array
'(1 => Unlimited_Files),
2498 (Cname => new S'("LIST"),
2499 Usage
=> new S
'("GNAT LIST /qualifiers object_or_ali_file"),
2501 Unixcmd => new S'("gnatls"),
2503 Switches
=> List_Switches
'Access,
2504 Params
=> new Parameter_Array
'(1 => File),
2508 (Cname => new S'("MAKE"),
2509 Usage
=> new S
'("GNAT MAKE file /qualifiers (includes "
2510 & "COMPILE /qualifiers)"),
2512 Unixcmd => new S'("gnatmake"),
2514 Switches
=> Make_Switches
'Access,
2515 Params
=> new Parameter_Array
'(1 => File),
2519 (Cname => new S'("NAME"),
2520 Usage
=> new S
'("GNAT NAME /qualifiers naming-pattern "
2521 & "[naming-patterns]"),
2523 Unixcmd => new S'("gnatname"),
2525 Switches
=> Name_Switches
'Access,
2526 Params
=> new Parameter_Array
'(1 => Unlimited_As_Is),
2530 (Cname => new S'("PREPROCESS"),
2531 Usage
=> new S
'("GNAT PREPROCESS ifile ofile dfile /qualifiers"),
2533 Unixcmd => new S'("gnatprep"),
2535 Switches
=> Prep_Switches
'Access,
2536 Params
=> new Parameter_Array
'(1 .. 3 => File),
2540 (Cname => new S'("SHARED"),
2541 Usage
=> new S
'("GNAT SHARED [obj_&_lib_&_exe_&_opt"
2542 & "files] /qualifiers"),
2544 Unixcmd => new S'("gcc"),
2545 Unixsws
=> new Argument_List
'(new String'("-shared")
2546 & Init_Object_Dirs
),
2547 Switches
=> Shared_Switches
'Access,
2548 Params
=> new Parameter_Array
'(1 => Unlimited_Files),
2552 (Cname => new S'("STANDARD"),
2553 Usage
=> new S
'("GNAT STANDARD"),
2555 Unixcmd => new S'("gnatpsta"),
2557 Switches
=> Standard_Switches
'Access,
2558 Params
=> new Parameter_Array
'(1 .. 0 => File),
2562 (Cname => new S'("STUB"),
2563 Usage
=> new S
'("GNAT STUB file [directory]/qualifiers"),
2565 Unixcmd => new S'("gnatstub"),
2567 Switches
=> Stub_Switches
'Access,
2568 Params
=> new Parameter_Array
'(1 => File, 2 => Optional_File),
2572 (Cname => new S'("XREF"),
2573 Usage
=> new S
'("GNAT XREF filespec[,...] /qualifiers"),
2575 Unixcmd => new S'("gnatxref"),
2577 Switches
=> Xref_Switches
'Access,
2578 Params
=> new Parameter_Array
'(1 => Files_Or_Wildcard),
2586 procedure Non_VMS_Usage is
2590 Put_Line ("List of available commands");
2593 for C in Command_List'Range loop
2594 if not Command_List (C).VMS_Only then
2595 Put ("GNAT " & Command_List (C).Cname.all);
2597 Put (Command_List (C).Unixcmd.all);
2600 Sws : Argument_List_Access renames Command_List (C).Unixsws;
2603 for J in Sws'Range loop
2615 Put_Line ("Commands FIND, LIST and XREF accept project file " &
2616 "switches -vPx, -Pprj and -Xnam=val");
2620 --------------------
2621 -- VMS_Conversion --
2622 --------------------
2624 procedure VMS_Conversion (The_Command : out Command_Type) is
2628 -- First we must preprocess the string form of the command and options
2629 -- list into the internal form that we use.
2631 for C in Real_Command_Type loop
2634 Command : Item_Ptr := new Command_Item;
2636 Last_Switch : Item_Ptr;
2637 -- Last switch in list
2640 -- Link new command item into list of commands
2642 if Last_Command = null then
2643 Commands := Command;
2645 Last_Command.Next := Command;
2648 Last_Command := Command;
2650 -- Fill in fields of new command item
2652 Command.Name := Command_List (C).Cname;
2653 Command.Usage := Command_List (C).Usage;
2654 Command.Command := C;
2656 if Command_List (C).Unixsws = null then
2657 Command.Unix_String := Command_List (C).Unixcmd;
2660 Cmd : String (1 .. 5_000);
2661 Last : Natural := 0;
2662 Sws : Argument_List_Access := Command_List (C).Unixsws;
2665 Cmd (1 .. Command_List (C).Unixcmd'Length) :=
2666 Command_List (C).Unixcmd.all;
2667 Last := Command_List (C).Unixcmd'Length;
2669 for J in Sws'Range loop
2672 Cmd (Last + 1 .. Last + Sws (J)'Length) :=
2674 Last := Last + Sws (J)'Length;
2677 Command.Unix_String := new String'(Cmd
(1 .. Last
));
2681 Command
.Params
:= Command_List
(C
).Params
;
2682 Command
.Defext
:= Command_List
(C
).Defext
;
2684 Validate_Command_Or_Option
(Command
.Name
);
2686 -- Process the switch list
2688 for S
in Command_List
(C
).Switches
'Range loop
2690 SS
: constant String_Ptr
:= Command_List
(C
).Switches
(S
);
2692 P
: Natural := SS
'First;
2693 Sw
: Item_Ptr
:= new Switch_Item
;
2695 Last_Opt
: Item_Ptr
;
2696 -- Pointer to last option
2699 -- Link new switch item into list of switches
2701 if Last_Switch
= null then
2702 Command
.Switches
:= Sw
;
2704 Last_Switch
.Next
:= Sw
;
2709 -- Process switch string, first get name
2711 while SS
(P
) /= ' ' and SS
(P
) /= '=' loop
2715 Sw
.Name
:= new String'(SS (SS'First .. P - 1));
2717 -- Direct translation case
2719 if SS (P) = ' ' then
2720 Sw.Translation := T_Direct;
2721 Sw.Unix_String := new String'(SS
(P
+ 1 .. SS
'Last));
2722 Validate_Unix_Switch
(Sw
.Unix_String
);
2724 if SS
(P
- 1) = '>' then
2725 Sw
.Translation
:= T_Other
;
2727 elsif SS
(P
+ 1) = '`' then
2730 -- Create the inverted case (/NO ..)
2732 elsif SS
(SS
'First + 1 .. SS
'First + 2) /= "NO" then
2733 Sw
:= new Switch_Item
;
2734 Last_Switch
.Next
:= Sw
;
2738 new String'("/NO" & SS (SS'First + 1 .. P - 1));
2739 Sw.Translation := T_Direct;
2740 Sw.Unix_String := Invert_Sense (SS (P + 1 .. SS'Last));
2741 Validate_Unix_Switch (Sw.Unix_String);
2744 -- Directories translation case
2746 elsif SS (P + 1) = '*' then
2747 pragma Assert (SS (SS'Last) = '*');
2748 Sw.Translation := T_Directories;
2749 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2750 Validate_Unix_Switch
(Sw
.Unix_String
);
2752 -- Directory translation case
2754 elsif SS
(P
+ 1) = '%' then
2755 pragma Assert
(SS
(SS
'Last) = '%');
2756 Sw
.Translation
:= T_Directory
;
2757 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2758 Validate_Unix_Switch (Sw.Unix_String);
2760 -- File translation case
2762 elsif SS (P + 1) = '@
' then
2763 pragma Assert (SS (SS'Last) = '@
');
2764 Sw.Translation := T_File;
2765 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2766 Validate_Unix_Switch
(Sw
.Unix_String
);
2768 -- No space file translation case
2770 elsif SS
(P
+ 1) = '<' then
2771 pragma Assert
(SS
(SS
'Last) = '>');
2772 Sw
.Translation
:= T_No_Space_File
;
2773 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2774 Validate_Unix_Switch (Sw.Unix_String);
2776 -- Numeric translation case
2778 elsif SS (P + 1) = '#
' then
2779 pragma Assert (SS (SS'Last) = '#
');
2780 Sw.Translation := T_Numeric;
2781 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2782 Validate_Unix_Switch
(Sw
.Unix_String
);
2784 -- Alphanumerplus translation case
2786 elsif SS
(P
+ 1) = '|' then
2787 pragma Assert
(SS
(SS
'Last) = '|');
2788 Sw
.Translation
:= T_Alphanumplus
;
2789 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last - 1));
2790 Validate_Unix_Switch (Sw.Unix_String);
2792 -- String translation case
2794 elsif SS (P + 1) = '"' then
2795 pragma Assert (SS (SS'Last) = '"');
2796 Sw.Translation := T_String;
2797 Sw.Unix_String := new String'(SS
(P
+ 2 .. SS
'Last - 1));
2798 Validate_Unix_Switch
(Sw
.Unix_String
);
2800 -- Commands translation case
2802 elsif SS
(P
+ 1) = '?' then
2803 Sw
.Translation
:= T_Commands
;
2804 Sw
.Unix_String
:= new String'(SS (P + 2 .. SS'Last));
2806 -- Options translation case
2809 Sw.Translation := T_Options;
2810 Sw.Unix_String := new String'("");
2812 P
:= P
+ 1; -- bump past =
2813 while P
<= SS
'Last loop
2815 Opt
: Item_Ptr
:= new Option_Item
;
2819 -- Link new option item into options list
2821 if Last_Opt
= null then
2824 Last_Opt
.Next
:= Opt
;
2829 -- Fill in fields of new option item
2832 while SS
(Q
) /= ' ' loop
2836 Opt
.Name
:= new String'(SS (P .. Q - 1));
2837 Validate_Command_Or_Option (Opt.Name);
2842 while Q <= SS'Last and then SS (Q) /= ' ' loop
2846 Opt.Unix_String := new String'(SS
(P
.. Q
- 1));
2847 Validate_Unix_Switch
(Opt
.Unix_String
);
2857 -- If no parameters, give complete list of commands
2859 if Argument_Count
= 0 then
2862 Put_Line
("List of available commands");
2865 while Commands
/= null loop
2866 Put
(Commands
.Usage
.all);
2868 Put_Line
(Commands
.Unix_String
.all);
2869 Commands
:= Commands
.Next
;
2877 -- Loop through arguments
2879 while Arg_Num
<= Argument_Count
loop
2881 Process_Argument
: declare
2882 Argv
: String_Access
;
2885 function Get_Arg_End
2889 -- Begins looking at Arg_Idx + 1 and returns the index of the
2890 -- last character before a slash or else the index of the last
2891 -- character in the string Argv.
2897 function Get_Arg_End
2903 for J
in Arg_Idx
+ 1 .. Argv
'Last loop
2904 if Argv
(J
) = '/' then
2912 -- Start of processing for Process_Argument
2915 Argv
:= new String'(Argument (Arg_Num));
2916 Arg_Idx := Argv'First;
2918 <<Tryagain_After_Coalesce>>
2921 Next_Arg_Idx : Integer;
2922 Arg : String_Access;
2925 Next_Arg_Idx := Get_Arg_End (Argv.all, Arg_Idx);
2926 Arg := new String'(Argv
(Arg_Idx
.. Next_Arg_Idx
));
2928 -- The first one must be a command name
2930 if Arg_Num
= 1 and then Arg_Idx
= Argv
'First then
2932 Command
:= Matching_Name
(Arg
.all, Commands
);
2934 if Command
= null then
2938 The_Command
:= Command
.Command
;
2940 -- Give usage information if only command given
2942 if Argument_Count
= 1 and then Next_Arg_Idx
= Argv
'Last
2943 and then Command
.Command
/= Standard
2948 ("List of available qualifiers and options");
2951 Put
(Command
.Usage
.all);
2953 Put_Line
(Command
.Unix_String
.all);
2956 Sw
: Item_Ptr
:= Command
.Switches
;
2959 while Sw
/= null loop
2963 case Sw
.Translation
is
2967 Put_Line
(Sw
.Unix_String
.all &
2972 Put_Line
(Sw
.Unix_String
.all);
2974 when T_Directories
=>
2975 Put
("=(direc,direc,..direc)");
2977 Put
(Sw
.Unix_String
.all);
2979 Put
(Sw
.Unix_String
.all);
2980 Put_Line
(" direc ...");
2985 Put
(Sw
.Unix_String
.all);
2987 if Sw
.Unix_String
(Sw
.Unix_String
'Last)
2993 Put_Line
("directory ");
2995 when T_File | T_No_Space_File
=>
2998 Put
(Sw
.Unix_String
.all);
3000 if Sw
.Translation
= T_File
3001 and then Sw
.Unix_String
3002 (Sw
.Unix_String
'Last)
3014 if Sw
.Unix_String
(Sw
.Unix_String
'First)
3018 (Sw
.Unix_String
'First + 1
3019 .. Sw
.Unix_String
'Last));
3021 Put
(Sw
.Unix_String
.all);
3026 when T_Alphanumplus
=>
3030 if Sw
.Unix_String
(Sw
.Unix_String
'First)
3034 (Sw
.Unix_String
'First + 1
3035 .. Sw
.Unix_String
'Last));
3037 Put
(Sw
.Unix_String
.all);
3049 Put
(Sw
.Unix_String
.all);
3051 if Sw
.Unix_String
(Sw
.Unix_String
'Last)
3061 Put
(" (switches for ");
3063 (Sw
.Unix_String
'First + 7
3064 .. Sw
.Unix_String
'Last));
3068 (Sw
.Unix_String
'First
3069 .. Sw
.Unix_String
'First + 5));
3070 Put_Line
(" switches");
3074 Opt
: Item_Ptr
:= Sw
.Options
;
3077 Put_Line
("=(option,option..)");
3079 while Opt
/= null loop
3083 if Opt
= Sw
.Options
then
3088 Put_Line
(Opt
.Unix_String
.all);
3102 -- Place (Command.Unix_String.all);
3104 -- Special handling for internal debugging switch /?
3106 elsif Arg
.all = "/?" then
3107 Display_Command
:= True;
3109 -- Copy -switch unchanged
3111 elsif Arg
(Arg
'First) = '-' then
3115 -- Copy quoted switch with quotes stripped
3117 elsif Arg
(Arg
'First) = '"' then
3118 if Arg
(Arg
'Last) /= '"' then
3119 Put
(Standard_Error
, "misquoted argument: ");
3120 Put_Line
(Standard_Error
, Arg
.all);
3121 Errors
:= Errors
+ 1;
3125 Place
(Arg
(Arg
'First + 1 .. Arg
'Last - 1));
3128 -- Parameter Argument
3130 elsif Arg
(Arg
'First) /= '/'
3131 and then Make_Commands_Active
= null
3133 Param_Count
:= Param_Count
+ 1;
3135 if Param_Count
<= Command
.Params
'Length then
3137 case Command
.Params
(Param_Count
) is
3139 when File | Optional_File
=>
3141 Normal_File
: String_Access
3142 := To_Canonical_File_Spec
(Arg
.all);
3145 Place_Lower
(Normal_File
.all);
3147 if Is_Extensionless
(Normal_File
.all)
3148 and then Command
.Defext
/= " "
3151 Place
(Command
.Defext
);
3155 when Unlimited_Files
=>
3157 Normal_File
: String_Access
3158 := To_Canonical_File_Spec
(Arg
.all);
3160 File_Is_Wild
: Boolean := False;
3161 File_List
: String_Access_List_Access
;
3163 for I
in Arg
'Range loop
3165 or else Arg
(I
) = '%'
3167 File_Is_Wild
:= True;
3171 if File_Is_Wild
then
3172 File_List
:= To_Canonical_File_List
3175 for I
in File_List
.all'Range loop
3177 Place_Lower
(File_List
.all (I
).all);
3181 Place_Lower
(Normal_File
.all);
3183 if Is_Extensionless
(Normal_File
.all)
3184 and then Command
.Defext
/= " "
3187 Place
(Command
.Defext
);
3191 Param_Count
:= Param_Count
- 1;
3198 when Unlimited_As_Is
=>
3201 Param_Count
:= Param_Count
- 1;
3203 when Files_Or_Wildcard
=>
3205 -- Remove spaces from a comma separated list
3206 -- of file names and adjust control variables
3209 while Arg_Num
< Argument_Count
and then
3210 (Argv
(Argv
'Last) = ',' xor
3211 Argument
(Arg_Num
+ 1)
3212 (Argument
(Arg_Num
+ 1)'First) = ',')
3215 (Argv.all & Argument (Arg_Num + 1));
3216 Arg_Num := Arg_Num + 1;
3217 Arg_Idx := Argv'First;
3219 Get_Arg_End (Argv.all, Arg_Idx);
3221 (Argv
(Arg_Idx
.. Next_Arg_Idx
));
3224 -- Parse the comma separated list of VMS
3225 -- filenames and place them on the command
3226 -- line as space separated Unix style
3227 -- filenames. Lower case and add default
3228 -- extension as appropriate.
3231 Arg1_Idx
: Integer := Arg
'First;
3233 function Get_Arg1_End
3234 (Arg
: String; Arg_Idx
: Integer)
3236 -- Begins looking at Arg_Idx + 1 and
3237 -- returns the index of the last character
3238 -- before a comma or else the index of the
3239 -- last character in the string Arg.
3241 function Get_Arg1_End
3242 (Arg
: String; Arg_Idx
: Integer)
3246 for I
in Arg_Idx
+ 1 .. Arg
'Last loop
3247 if Arg
(I
) = ',' then
3258 Next_Arg1_Idx
: Integer :=
3259 Get_Arg1_End
(Arg
.all, Arg1_Idx
);
3262 Arg
(Arg1_Idx
.. Next_Arg1_Idx
);
3264 Normal_File
: String_Access
:=
3265 To_Canonical_File_Spec
(Arg1
);
3269 Place_Lower
(Normal_File
.all);
3271 if Is_Extensionless
(Normal_File
.all)
3272 and then Command
.Defext
/= " "
3275 Place
(Command
.Defext
);
3278 Arg1_Idx
:= Next_Arg1_Idx
+ 1;
3281 exit when Arg1_Idx
> Arg
'Last;
3283 -- Don't allow two or more commas in
3286 if Arg
(Arg1_Idx
) = ',' then
3287 Arg1_Idx
:= Arg1_Idx
+ 1;
3288 if Arg1_Idx
> Arg
'Last or else
3289 Arg
(Arg1_Idx
) = ','
3293 "Malformed Parameter: " &
3295 Put
(Standard_Error
, "usage: ");
3296 Put_Line
(Standard_Error
,
3307 -- Qualifier argument
3314 Endp
: Natural := 0; -- avoid warning!
3319 while SwP
< Arg
'Last
3320 and then Arg
(SwP
+ 1) /= '='
3325 -- At this point, the switch name is in
3326 -- Arg (Arg'First..SwP) and if that is not the
3327 -- whole switch, then there is an equal sign at
3328 -- Arg (SwP + 1) and the rest of Arg is what comes
3329 -- after the equal sign.
3331 -- If make commands are active, see if we have
3332 -- another COMMANDS_TRANSLATION switch belonging
3335 if Make_Commands_Active
/= null then
3338 (Arg
(Arg
'First .. SwP
),
3343 and then Sw
.Translation
= T_Commands
3350 (Arg
(Arg
'First .. SwP
),
3351 Make_Commands_Active
.Switches
,
3355 -- For case of GNAT MAKE or CHOP, if we cannot
3356 -- find the switch, then see if it is a
3357 -- recognized compiler switch instead, and if
3358 -- so process the compiler switch.
3360 elsif Command
.Name
.all = "MAKE"
3361 or else Command
.Name
.all = "CHOP" then
3364 (Arg
(Arg
'First .. SwP
),
3371 (Arg
(Arg
'First .. SwP
),
3373 ("COMPILE", Commands
).Switches
,
3377 -- For all other cases, just search the relevant
3383 (Arg
(Arg
'First .. SwP
),
3389 case Sw
.Translation
is
3392 Place_Unix_Switches
(Sw
.Unix_String
);
3394 and then Arg
(SwP
+ 1) = '='
3396 Put
(Standard_Error
,
3397 "qualifier options ignored: ");
3398 Put_Line
(Standard_Error
, Arg
.all);
3401 when T_Directories
=>
3402 if SwP
+ 1 > Arg
'Last then
3403 Put
(Standard_Error
,
3404 "missing directories for: ");
3405 Put_Line
(Standard_Error
, Arg
.all);
3406 Errors
:= Errors
+ 1;
3408 elsif Arg
(SwP
+ 2) /= '(' then
3412 elsif Arg
(Arg
'Last) /= ')' then
3414 -- Remove spaces from a comma separated
3415 -- list of file names and adjust
3416 -- control variables accordingly.
3418 if Arg_Num
< Argument_Count
and then
3419 (Argv
(Argv
'Last) = ',' xor
3420 Argument
(Arg_Num
+ 1)
3421 (Argument
(Arg_Num
+ 1)'First) = ',')
3424 new String'(Argv.all
3427 Arg_Num := Arg_Num + 1;
3428 Arg_Idx := Argv'First;
3430 := Get_Arg_End (Argv.all, Arg_Idx);
3432 (Argv
(Arg_Idx
.. Next_Arg_Idx
));
3433 goto Tryagain_After_Coalesce
;
3436 Put
(Standard_Error
,
3437 "incorrectly parenthesized " &
3438 "or malformed argument: ");
3439 Put_Line
(Standard_Error
, Arg
.all);
3440 Errors
:= Errors
+ 1;
3444 Endp
:= Arg
'Last - 1;
3447 while SwP
<= Endp
loop
3449 Dir_Is_Wild
: Boolean := False;
3450 Dir_Maybe_Is_Wild
: Boolean := False;
3451 Dir_List
: String_Access_List_Access
;
3456 and then Arg
(P2
+ 1) /= ','
3459 -- A wildcard directory spec on
3460 -- VMS will contain either * or
3463 if Arg
(P2
) = '*' then
3464 Dir_Is_Wild
:= True;
3466 elsif Arg
(P2
) = '%' then
3467 Dir_Is_Wild
:= True;
3469 elsif Dir_Maybe_Is_Wild
3470 and then Arg
(P2
) = '.'
3471 and then Arg
(P2
+ 1) = '.'
3473 Dir_Is_Wild
:= True;
3474 Dir_Maybe_Is_Wild
:= False;
3476 elsif Dir_Maybe_Is_Wild
then
3477 Dir_Maybe_Is_Wild
:= False;
3479 elsif Arg
(P2
) = '.'
3480 and then Arg
(P2
+ 1) = '.'
3482 Dir_Maybe_Is_Wild
:= True;
3489 if (Dir_Is_Wild
) then
3490 Dir_List
:= To_Canonical_File_List
3491 (Arg
(SwP
.. P2
), True);
3493 for I
in Dir_List
.all'Range loop
3497 (Dir_List
.all (I
).all);
3503 (To_Canonical_Dir_Spec
3504 (Arg
(SwP
.. P2
), False).all);
3512 if SwP
+ 1 > Arg
'Last then
3513 Put
(Standard_Error
,
3514 "missing directory for: ");
3515 Put_Line
(Standard_Error
, Arg
.all);
3516 Errors
:= Errors
+ 1;
3519 Place_Unix_Switches
(Sw
.Unix_String
);
3521 -- Some switches end in "=". No space
3525 (Sw
.Unix_String
'Last) /= '='
3531 (To_Canonical_Dir_Spec
3532 (Arg
(SwP
+ 2 .. Arg
'Last),
3536 when T_File | T_No_Space_File
=>
3537 if SwP
+ 1 > Arg
'Last then
3538 Put
(Standard_Error
,
3539 "missing file for: ");
3540 Put_Line
(Standard_Error
, Arg
.all);
3541 Errors
:= Errors
+ 1;
3544 Place_Unix_Switches
(Sw
.Unix_String
);
3546 -- Some switches end in "=". No space
3549 if Sw
.Translation
= T_File
3550 and then Sw
.Unix_String
3551 (Sw
.Unix_String
'Last) /= '='
3557 (To_Canonical_File_Spec
3558 (Arg
(SwP
+ 2 .. Arg
'Last)).all);
3563 OK_Integer
(Arg
(SwP
+ 2 .. Arg
'Last))
3565 Place_Unix_Switches
(Sw
.Unix_String
);
3566 Place
(Arg
(SwP
+ 2 .. Arg
'Last));
3569 Put
(Standard_Error
, "argument for ");
3570 Put
(Standard_Error
, Sw
.Name
.all);
3572 (Standard_Error
, " must be numeric");
3573 Errors
:= Errors
+ 1;
3576 when T_Alphanumplus
=>
3579 (Arg
(SwP
+ 2 .. Arg
'Last))
3581 Place_Unix_Switches
(Sw
.Unix_String
);
3582 Place
(Arg
(SwP
+ 2 .. Arg
'Last));
3585 Put
(Standard_Error
, "argument for ");
3586 Put
(Standard_Error
, Sw
.Name
.all);
3587 Put_Line
(Standard_Error
,
3588 " must be alphanumeric");
3589 Errors
:= Errors
+ 1;
3594 -- A String value must be extended to the
3595 -- end of the Argv, otherwise strings like
3596 -- "foo/bar" get split at the slash.
3598 -- The begining and ending of the string
3599 -- are flagged with embedded nulls which
3600 -- are removed when building the Spawn
3601 -- call. Nulls are use because they won't
3602 -- show up in a /? output. Quotes aren't
3603 -- used because that would make it
3604 -- difficult to embed them.
3606 Place_Unix_Switches
(Sw
.Unix_String
);
3607 if Next_Arg_Idx
/= Argv
'Last then
3608 Next_Arg_Idx
:= Argv
'Last;
3610 (Argv (Arg_Idx .. Next_Arg_Idx));
3613 while SwP < Arg'Last and then
3614 Arg (SwP + 1) /= '=' loop
3619 Place (Arg (SwP + 2 .. Arg'Last));
3624 -- Output -largs/-bargs/-cargs
3627 Place (Sw.Unix_String
3628 (Sw.Unix_String'First ..
3629 Sw.Unix_String'First + 5));
3631 -- Set source of new commands, also
3632 -- setting this non-null indicates that
3633 -- we are in the special commands mode
3634 -- for processing the -xargs case.
3636 Make_Commands_Active :=
3639 (Sw.Unix_String'First + 7 ..
3640 Sw.Unix_String'Last),
3644 if SwP + 1 > Arg'Last then
3646 (Sw.Options.Unix_String);
3649 elsif Arg (SwP + 2) /= '(' then
3653 elsif Arg (Arg'Last) /= ')' then
3656 "incorrectly parenthesized " &
3658 Put_Line (Standard_Error, Arg.all);
3659 Errors := Errors + 1;
3664 Endp := Arg'Last - 1;
3667 while SwP <= Endp loop
3671 and then Arg (P2 + 1) /= ','
3676 -- Option name is in Arg (SwP .. P2)
3678 Opt := Matching_Name (Arg (SwP .. P2),
3691 (new String'(Sw
.Unix_String
.all &
3699 Arg_Idx
:= Next_Arg_Idx
+ 1;
3702 exit when Arg_Idx
> Argv
'Last;
3705 end Process_Argument
;
3707 Arg_Num
:= Arg_Num
+ 1;
3710 if Display_Command
then
3711 Put
(Standard_Error
, "generated command -->");
3712 Put
(Standard_Error
, Command_List
(The_Command
).Unixcmd
.all);
3714 if Command_List
(The_Command
).Unixsws
/= null then
3715 for J
in Command_List
(The_Command
).Unixsws
'Range loop
3716 Put
(Standard_Error
, " ");
3717 Put
(Standard_Error
,
3718 Command_List
(The_Command
).Unixsws
(J
).all);
3722 Put
(Standard_Error
, " ");
3723 Put
(Standard_Error
, String (Buffer
.Table
(1 .. Buffer
.Last
)));
3724 Put
(Standard_Error
, "<--");
3725 New_Line
(Standard_Error
);
3729 -- Gross error checking that the number of parameters is correct.
3730 -- Not applicable to Unlimited_Files parameters.
3732 if (Param_Count
= Command
.Params
'Length - 1
3733 and then Command
.Params
(Param_Count
+ 1) = Unlimited_Files
)
3734 or else Param_Count
<= Command
.Params
'Length
3739 Put_Line
(Standard_Error
,
3740 "Parameter count of "
3741 & Integer'Image (Param_Count
)
3742 & " not equal to expected "
3743 & Integer'Image (Command
.Params
'Length));
3744 Put
(Standard_Error
, "usage: ");
3745 Put_Line
(Standard_Error
, Command
.Usage
.all);
3746 Errors
:= Errors
+ 1;
3752 -- Prepare arguments for a call to spawn, filtering out
3753 -- embedded nulls place there to delineate strings.
3757 Inside_Nul
: Boolean := False;
3758 Arg
: String (1 .. 1024);
3764 while P1
<= Buffer
.Last
and then Buffer
.Table
(P1
) = ' ' loop
3769 Arg
(Arg_Ctr
) := Buffer
.Table
(P1
);
3771 while P1
<= Buffer
.Last
loop
3773 if Buffer
.Table
(P1
) = ASCII
.NUL
then
3775 Inside_Nul
:= False;
3781 if Buffer
.Table
(P1
) = ' ' and then not Inside_Nul
then
3783 Arg_Ctr
:= Arg_Ctr
+ 1;
3784 Arg
(Arg_Ctr
) := Buffer
.Table
(P1
);
3787 Last_Switches
.Increment_Last
;
3790 while P2
< Buffer
.Last
3791 and then (Buffer
.Table
(P2
+ 1) /= ' ' or else
3795 Arg_Ctr
:= Arg_Ctr
+ 1;
3796 Arg
(Arg_Ctr
) := Buffer
.Table
(P2
);
3797 if Buffer
.Table
(P2
) = ASCII
.NUL
then
3798 Arg_Ctr
:= Arg_Ctr
- 1;
3800 Inside_Nul
:= False;
3807 Last_Switches
.Table
(Last_Switches
.Last
) :=
3808 new String'(String (Arg (1 .. Arg_Ctr)));
3811 Arg (Arg_Ctr) := Buffer.Table (P1);
3818 -------------------------------------
3819 -- Start of processing for GNATCmd --
3820 -------------------------------------
3833 Last_Switches.Set_Last (0);
3835 First_Switches.Init;
3836 First_Switches.Set_Last (0);
3838 -- If on VMS, or if VMS emulation is on, convert VMS style /qualifiers,
3839 -- filenames and pathnames to Unix style.
3842 or else To_Lower (Getenv ("EMULATE_VMS").all) = "true"
3844 VMS_Conversion (The_Command);
3846 -- If not on VMS, scan the command line directly
3849 if Argument_Count = 0 then
3854 if Argument_Count > 1 and then Argument (1) = "-v" then
3855 Opt.Verbose_Mode := True;
3859 The_Command := Real_Command_Type'Value (Argument (Command_Arg));
3861 if Command_List (The_Command).VMS_Only then
3863 Fail ("Command """ & Command_List (The_Command).Cname.all &
3864 """ can only be used on VMS");
3867 when Constraint_Error =>
3869 -- Check if it is an alternate command
3871 Alternate : Alternate_Command;
3874 Alternate := Alternate_Command'Value
3875 (Argument (Command_Arg));
3876 The_Command := Corresponding_To (Alternate);
3879 when Constraint_Error =>
3881 Fail ("Unknown command: " & Argument (Command_Arg));
3885 for Arg in Command_Arg + 1 .. Argument_Count loop
3886 Last_Switches.Increment_Last;
3887 Last_Switches.Table (Last_Switches.Last) :=
3888 new String'(Argument
(Arg
));
3894 Program
: constant String :=
3895 Program_Name
(Command_List
(The_Command
).Unixcmd
.all).all;
3897 Exec_Path
: String_Access
;
3900 -- Locate the executable for the command
3902 Exec_Path
:= Locate_Exec_On_Path
(Program
);
3904 if Exec_Path
= null then
3905 Put_Line
(Standard_Error
, "Couldn't locate " & Program
);
3909 -- If there are switches for the executable, put them as first switches
3911 if Command_List
(The_Command
).Unixsws
/= null then
3912 for J
in Command_List
(The_Command
).Unixsws
'Range loop
3913 First_Switches
.Increment_Last
;
3914 First_Switches
.Table
(First_Switches
.Last
) :=
3915 Command_List
(The_Command
).Unixsws
(J
);
3919 -- For BIND, FIND, LINK, LIST and XREF, look for project file related
3922 if The_Command
= Bind
3923 or else The_Command
= Find
3924 or else The_Command
= Link
3925 or else The_Command
= List
3926 or else The_Command
= Xref
3930 Tool_Package_Name
:= Name_Binder
;
3932 Tool_Package_Name
:= Name_Finder
;
3934 Tool_Package_Name
:= Name_Linker
;
3936 Tool_Package_Name
:= Name_Gnatls
;
3938 Tool_Package_Name
:= Name_Cross_Reference
;
3944 Arg_Num
: Positive := 1;
3945 Argv
: String_Access
;
3947 procedure Remove_Switch
(Num
: Positive);
3948 -- Remove a project related switch from table Last_Switches
3954 procedure Remove_Switch
(Num
: Positive) is
3956 Last_Switches
.Table
(Num
.. Last_Switches
.Last
- 1) :=
3957 Last_Switches
.Table
(Num
+ 1 .. Last_Switches
.Last
);
3958 Last_Switches
.Decrement_Last
;
3961 -- Start of processing for ??? (need block name here)
3964 while Arg_Num
<= Last_Switches
.Last
loop
3965 Argv
:= Last_Switches
.Table
(Arg_Num
);
3967 if Argv
(Argv
'First) = '-' then
3968 if Argv
'Length = 1 then
3969 Fail
("switch character cannot be followed by a blank");
3972 -- The two style project files (-p and -P) cannot be used
3975 if (The_Command
= Find
or else The_Command
= Xref
)
3976 and then Argv
(2) = 'p'
3978 Old_Project_File_Used
:= True;
3979 if Project_File
/= null then
3980 Fail
("-P and -p cannot be used together");
3984 -- -vPx Specify verbosity while parsing project files
3987 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "vP"
3989 case Argv
(Argv
'Last) is
3991 Current_Verbosity
:= Prj
.Default
;
3993 Current_Verbosity
:= Prj
.Medium
;
3995 Current_Verbosity
:= Prj
.High
;
3997 Fail
("Invalid switch: " & Argv
.all);
4000 Remove_Switch
(Arg_Num
);
4002 -- -Pproject_file Specify project file to be used
4004 elsif Argv
'Length >= 3
4005 and then Argv
(Argv
'First + 1) = 'P'
4008 -- Only one -P switch can be used
4010 if Project_File
/= null then
4012 ": second project file forbidden (first is """ &
4013 Project_File
.all & """)");
4015 -- The two style project files (-p and -P) cannot be
4018 elsif Old_Project_File_Used
then
4019 Fail
("-p and -P cannot be used together");
4023 new String'(Argv (Argv'First + 2 .. Argv'Last));
4026 Remove_Switch (Arg_Num);
4028 -- -Xexternal=value Specify an external reference to be
4029 -- used in project files
4031 elsif Argv'Length >= 5
4032 and then Argv (Argv'First + 1) = 'X
'
4035 Equal_Pos : constant Natural :=
4036 Index ('=', Argv (Argv'First + 2 .. Argv'Last));
4038 if Equal_Pos >= Argv'First + 3 and then
4039 Equal_Pos /= Argv'Last then
4040 Add (External_Name =>
4041 Argv (Argv'First + 2 .. Equal_Pos - 1),
4042 Value => Argv (Equal_Pos + 1 .. Argv'Last));
4045 " is not a valid external assignment.");
4049 Remove_Switch (Arg_Num);
4052 Arg_Num := Arg_Num + 1;
4056 Arg_Num := Arg_Num + 1;
4062 -- If there is a project file specified, parse it, get the switches
4063 -- for the tool and setup PATH environment variables.
4065 if Project_File /= null then
4066 Prj.Pars.Set_Verbosity (To => Current_Verbosity);
4069 (Project => Project,
4070 Project_File_Name => Project_File.all);
4072 if Project = Prj.No_Project then
4073 Fail ("""" & Project_File.all & """ processing failed");
4076 -- Check if a package with the name of the tool is in the project
4077 -- file and if there is one, get the switches, if any, and scan them.
4080 Data : Prj.Project_Data := Prj.Projects.Table (Project);
4081 Pkg : Prj.Package_Id :=
4083 (Name => Tool_Package_Name,
4084 In_Packages => Data.Decl.Packages);
4086 Element : Package_Element;
4088 Default_Switches_Array : Array_Element_Id;
4090 The_Switches : Prj.Variable_Value;
4091 Current : Prj.String_List_Id;
4092 The_String : String_Element;
4095 if Pkg /= No_Package then
4096 Element := Packages.Table (Pkg);
4098 -- Packages Gnatls has a single attribute Switches, that is
4099 -- not an associative array.
4101 if The_Command = List then
4104 (Variable_Name => Snames.Name_Switches,
4105 In_Variables => Element.Decl.Attributes);
4107 -- Packages Binder (for gnatbind), Cross_Reference (for
4108 -- gnatxref), Linker (for gnatlink) and Finder
4109 -- (for gnatfind) have an attributed Default_Switches,
4110 -- an associative array, indexed by the name of the
4111 -- programming language.
4113 Default_Switches_Array :=
4115 (Name => Name_Default_Switches,
4116 In_Arrays => Packages.Table (Pkg).Decl.Arrays);
4117 The_Switches := Prj.Util.Value_Of
4119 In_Array => Default_Switches_Array);
4123 -- If there are switches specified in the package of the
4124 -- project file corresponding to the tool, scan them.
4126 case The_Switches.Kind is
4127 when Prj.Undefined =>
4131 if String_Length (The_Switches.Value) > 0 then
4132 String_To_Name_Buffer (The_Switches.Value);
4133 First_Switches.Increment_Last;
4134 First_Switches.Table (First_Switches.Last) :=
4135 new String'(Name_Buffer
(1 .. Name_Len
));
4139 Current
:= The_Switches
.Values
;
4140 while Current
/= Prj
.Nil_String
loop
4141 The_String
:= String_Elements
.Table
(Current
);
4143 if String_Length
(The_String
.Value
) > 0 then
4144 String_To_Name_Buffer
(The_String
.Value
);
4145 First_Switches
.Increment_Last
;
4146 First_Switches
.Table
(First_Switches
.Last
) :=
4147 new String'(Name_Buffer (1 .. Name_Len));
4150 Current := The_String.Next;
4156 -- Set up the environment variables ADA_INCLUDE_PATH and
4157 -- ADA_OBJECTS_PATH.
4160 (Name => Ada_Include_Path,
4161 Value => Prj.Env.Ada_Include_Path (Project).all);
4163 (Name => Ada_Objects_Path,
4164 Value => Prj.Env.Ada_Objects_Path
4165 (Project, Including_Libraries => False).all);
4167 if The_Command = Bind or else The_Command = Link then
4170 (Projects.Table (Project).Object_Directory));
4173 if The_Command = Link then
4175 -- Add the default search directories, to be able to find
4176 -- libgnat in call to MLib.Utl.Lib_Directory.
4178 Add_Default_Search_Dirs;
4181 There_Are_Libraries : Boolean := False;
4184 -- Check if there are library project files
4186 if MLib.Tgt.Libraries_Are_Supported then
4187 Set_Libraries (Project, There_Are_Libraries);
4190 -- If there are, add the necessary additional switches
4192 if There_Are_Libraries then
4194 -- Add -L<lib_dir> -lgnarl -lgnat -Wl,-rpath,<lib_dir>
4196 Last_Switches.Increment_Last;
4197 Last_Switches.Table (Last_Switches.Last) :=
4198 new String'("-L" & MLib
.Utl
.Lib_Directory
);
4199 Last_Switches
.Increment_Last
;
4200 Last_Switches
.Table
(Last_Switches
.Last
) :=
4201 new String'("-lgnarl");
4202 Last_Switches.Increment_Last;
4203 Last_Switches.Table (Last_Switches.Last) :=
4204 new String'("-lgnat");
4207 Option
: constant String_Access
:=
4208 MLib
.Tgt
.Linker_Library_Path_Option
4209 (MLib
.Utl
.Lib_Directory
);
4212 if Option
/= null then
4213 Last_Switches
.Increment_Last
;
4214 Last_Switches
.Table
(Last_Switches
.Last
) :=
4223 -- Gather all the arguments and invoke the executable
4226 The_Args
: Argument_List
4227 (1 .. First_Switches
.Last
+ Last_Switches
.Last
);
4228 Arg_Num
: Natural := 0;
4230 for J
in 1 .. First_Switches
.Last
loop
4231 Arg_Num
:= Arg_Num
+ 1;
4232 The_Args
(Arg_Num
) := First_Switches
.Table
(J
);
4235 for J
in 1 .. Last_Switches
.Last
loop
4236 Arg_Num
:= Arg_Num
+ 1;
4237 The_Args
(Arg_Num
) := Last_Switches
.Table
(J
);
4240 if Opt
.Verbose_Mode
then
4241 Output
.Write_Str
(Exec_Path
.all);
4243 for Arg
in The_Args
'Range loop
4244 Output
.Write_Char
(' ');
4245 Output
.Write_Str
(The_Args
(Arg
).all);
4252 := Exit_Status
(Spawn
(Exec_Path
.all, The_Args
));
4259 Set_Exit_Status
(Failure
);
4262 Set_Exit_Status
(My_Exit_Status
);