1------------------------------------------------------------------------------ 2-- -- 3-- GPR TECHNOLOGY -- 4-- -- 5-- Copyright (C) 2006-2015, AdaCore -- 6-- -- 7-- This is free software; you can redistribute it and/or modify it under -- 8-- terms of the GNU General Public License as published by the Free Soft- -- 9-- ware Foundation; either version 3, or (at your option) any later ver- -- 10-- sion. This software is distributed in the hope that it will be useful, -- 11-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- 12-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- 13-- License for more details. You should have received a copy of the GNU -- 14-- General Public License distributed with GNAT; see file COPYING. If not, -- 15-- see <http://www.gnu.org/licenses/>. -- 16-- -- 17------------------------------------------------------------------------------ 18 19-- This unit is responsible for parsing the gprconfig knowledge base 20 21with Ada.Containers.Doubly_Linked_Lists; 22with Ada.Containers.Indefinite_Doubly_Linked_Lists; 23with Ada.Containers.Indefinite_Hashed_Maps; 24with Ada.Containers.Hashed_Maps; 25with Ada.Containers.Vectors; 26with Ada.Strings.Unbounded; 27 28with GNAT.Regpat; 29 30with GPR; use GPR; 31 32package GprConfig.Knowledge is 33 34 Generate_Error : exception; 35 -- To be raised when an error occurs during generation of config files 36 37 -------------------- 38 -- Knowledge base -- 39 -------------------- 40 -- The following types and subprograms manipulate the knowldge base. This 41 -- base is a set of XML files that describe how to find compilers that are 42 -- installed on the system and that match specific criterias. 43 44 type Knowledge_Base is private; 45 46 function Default_Knowledge_Base_Directory return String; 47 -- Return the default location of the knowledge database. This is based on 48 -- the installation directory of the executable. 49 50 procedure Parse_Knowledge_Base 51 (Base : in out Knowledge_Base; 52 Directory : String; 53 Parse_Compiler_Info : Boolean := True; 54 Validate : Boolean := False); 55 -- Parse info from the knowledge base, and store it in memory. 56 -- Only information relevant to the current host is parsed. 57 -- If Parse_Compiler_Info is False, then only the information about 58 -- target sets is parsed. 59 -- This procedure will raise Invalid_Knowledge_Base if the base contains 60 -- incorrect data. 61 -- If Validate is True, the contents of the knowledge base is first 62 -- validated with an XSD schema. 63 64 Invalid_Knowledge_Base : exception; 65 -- To be raised when an error occurred while parsing the knowledge base 66 67 Knowledge_Base_Validation_Error : exception; 68 -- Some files in the knowledge base are invalid. 69 70 ----------------- 71 -- Target sets -- 72 ----------------- 73 -- One of the information pieces contain in the database is a way to 74 -- normalize target names, since various names are used in different 75 -- contexts thus making it harder to write project files depending on the 76 -- target. 77 78 type Targets_Set_Id is private; 79 -- Identify a target aliases set 80 81 All_Target_Sets : constant Targets_Set_Id; 82 -- Matches all target sets 83 84 Unknown_Targets_Set : constant Targets_Set_Id; 85 -- Special target set when a target is not known 86 87 function Query_Targets_Set 88 (Base : Knowledge_Base; 89 Target : String) return Targets_Set_Id; 90 -- Get the target alias set id for a target, or Unknown_Targets_Set if 91 -- no such target is in the base. 92 93 procedure Get_Targets_Set 94 (Base : in out Knowledge_Base; 95 Target : String; 96 Id : out Targets_Set_Id); 97 -- Get the target alias set id for a target. If not already in the base, 98 -- add it. 99 100 function Normalized_Target 101 (Base : Knowledge_Base; 102 Set : Targets_Set_Id) return String; 103 -- Return the normalized name for a target set 104 105 --------------- 106 -- Compilers -- 107 --------------- 108 -- Most of the information in the database relates to compilers. However, 109 -- you do not have direct access to the generic description that explains 110 -- how to find compilers on the PATH and how to compute their attributes 111 -- (version, runtimes,...) Instead, this package gives you access to the 112 -- list of compilers that were found. The package ensures that all 113 -- information is only computed at most once, to save on system calls and 114 -- provide better performance. 115 116 type Compiler is private; 117 type Compiler_Access is access all Compiler; 118 119 function Runtime_Dir_Of (Comp : Compiler_Access) return Name_Id; 120 -- Return the name of the runtime directory for the compiler. Returns 121 -- No_Name if Comp is null. 122 123 package Compiler_Lists 124 is new Ada.Containers.Indefinite_Doubly_Linked_Lists (Compiler_Access); 125 -- A list of compilers 126 127 function Is_Selected (Comp : Compiler) return Boolean; 128 function Target (Comp : Compiler) return Name_Id; 129 130 procedure Set_Selection 131 (Compilers : in out Compiler_Lists.List; 132 Cursor : Compiler_Lists.Cursor; 133 Selected : Boolean); 134 procedure Set_Selection 135 (Comp : in out Compiler; 136 Selected : Boolean); 137 -- Toggle the selection status of a compiler in the list. 138 -- This does not check that the selection is consistent though (use 139 -- Is_Supported_Config to do this test) 140 141 function To_String 142 (Base : Knowledge_Base; 143 Comp : Compiler; 144 As_Config_Arg : Boolean; 145 Show_Target : Boolean := False; 146 Rank_In_List : Integer := -1; 147 Parser_Friendly : Boolean := False) return String; 148 -- Return a string representing the compiler. It is either the --config 149 -- argument (if As_Config_Arg is true) or the string to use in the 150 -- interactive menu otherwise. 151 -- If Rank_In_List is specified, it is written at the beginning of the 152 -- line. 153 -- If Parser_Friendly is set, then the list is displayed in a way that can 154 -- be easily parsed automatically 155 156 function To_String 157 (Base : Knowledge_Base; 158 Compilers : Compiler_Lists.List; 159 Selected_Only : Boolean; 160 Show_Target : Boolean := False; 161 Parser_Friendly : Boolean := False) return String; 162 -- Return the list of compilers. 163 -- Unselectable compilers are hidden. If Selected_Only is true, then only 164 -- compilers that are currently selected are displayed. 165 -- If Parser_Friendly is set, then the list is displayed in a way that can 166 -- be easily parsed automatically 167 168 function Display_Before (Comp1, Comp2 : Compiler_Access) return Boolean; 169 -- Whether Comp1 should be displayed before Comp2 when displaying lists of 170 -- compilers. This ensures that similar languages are grouped, among othe 171 -- things. 172 173 procedure Filter_Compilers_List 174 (Base : Knowledge_Base; 175 Compilers : in out Compiler_Lists.List; 176 For_Target_Set : Targets_Set_Id); 177 -- Based on the currently selected compilers, check which other compilers 178 -- can or cannot be selected by the user. 179 -- This is not the case if the resulting selection in Compilers is not a 180 -- supported config (multiple compilers for the same language, set of 181 -- compilers explicitly marked as unsupported in the knowledge base,...). 182 183 ------------------ 184 -- Command line -- 185 ------------------ 186 -- This package provides support for manipulating the --config command line 187 -- parameters. The intent is that they have the same form in all the tools 188 -- that support it. The information provides to --config might be partial 189 -- only, and this package provides support for completing it automatically 190 -- based on the knowledge base. 191 192 procedure Parse_Config_Parameter 193 (Base : Knowledge_Base; 194 Config : String; 195 Compiler : out Compiler_Access; 196 Requires_Compiler : out Boolean); 197 -- Parse the --config parameter, and store the (partial) information 198 -- found in Compiler. 199 -- When a switch matches a language that requires no compiler, 200 -- Requires_Compiler is set to False. 201 -- Raises Invalid_Config if Config is invalid 202 203 Invalid_Config : exception; 204 -- Raised when the user has specified an invalid --config switch 205 206 procedure Complete_Command_Line_Compilers 207 (Base : in out Knowledge_Base; 208 On_Target : Targets_Set_Id; 209 Filters : Compiler_Lists.List; 210 Compilers : in out Compiler_Lists.List); 211 -- In batch mode, the --config parameters indicate what compilers should be 212 -- selected. Each of these switch selects the first matching compiler 213 -- available, and all --config switch must match a compiler. 214 -- The information provided by the user does not have to be complete, and 215 -- this procedure completes all missing information like version, runtime, 216 -- and so on. 217 -- In gprconfig, it should only be called in batch mode, since otherwise 218 -- --config only acts as a filter for the compilers that are found through 219 -- the knowledge base. 220 -- Filters is the list specified by the user as --config, and contains 221 -- potentially partial information for each compiler. On output, Compilers 222 -- is completed with the full information for all compilers in Filters. If 223 -- at least one of the compilers in Filters cannot be found, Invalid_Config 224 -- is raised. 225 226 function Extra_Dirs_From_Filters 227 (Filters : Compiler_Lists.List) return String; 228 -- Compute the list of directories that should be prepended to the PATH 229 -- when searching for compilers. These are all the directories that the 230 -- user has explicitly specified in his filters (aka --config) 231 232 ----------------------------- 233 -- knowledge base contents -- 234 ----------------------------- 235 236 function Hash_Case_Insensitive 237 (Name : Name_Id) return Ada.Containers.Hash_Type; 238 package Variables_Maps is new Ada.Containers.Hashed_Maps 239 (Key_Type => Name_Id, 240 Element_Type => Name_Id, 241 Hash => Hash_Case_Insensitive, 242 Equivalent_Keys => "=", 243 "=" => "="); 244 245 No_Compiler : constant Compiler; 246 -- Describes one of the compilers found on the PATH. 247 -- Path is the directory that contains the compiler executable. 248 -- Path_Order is used for sorting in the interactive menu: it indicates the 249 -- index in $PATH of the directory, so that we can show first the compilers 250 -- that are first in path. 251 -- Any of these compilers can be selected by the user as part of a config. 252 -- However, to prevent incompatibilities, a compiler can be marked as not 253 -- selectable. This will be re-evaluated based on the current selection. 254 -- Complete is set to True if all the information about the compiler was 255 -- computed. It is set to False if the compiler was specified through a 256 -- command line argument --config, and part of the info needs to be 257 -- computed. 258 -- Index_In_List is used for the interactive menu, and is initialized 259 -- automatically. 260 261 type Compiler_Iterator is abstract tagged null record; 262 -- An iterator that searches for all known compilers in a list of 263 -- directories. Whenever a new compiler is found, the Callback primitive 264 -- operation is called. 265 266 procedure Callback 267 (Iterator : in out Compiler_Iterator; 268 Base : in out Knowledge_Base; 269 Comp : Compiler; 270 Runtime_Specified : Boolean; 271 From_Extra_Dir : Boolean; 272 Continue : out Boolean) is abstract; 273 -- Called whenever a new compiler is discovered. 274 -- It might be discovered either in a path added through a --config 275 -- parameter (in which case From_Extra_Dir is True), or in a path specified 276 -- in the environment variable $PATH (in which case it is False). If the 277 -- directory is both in Extra_Dirs and in $PATH, From_Extra_Dir is set to 278 -- False. 279 -- If Runtime_Specified is True, only filters with a specified runtime are 280 -- 281 -- On exit, Continue should be set to False if there is no need to discover 282 -- further compilers (however there will be no possibility to restart the 283 -- search at the same point later on). 284 285 procedure Foreach_Compiler_In_Path 286 (Iterator : in out Compiler_Iterator; 287 Base : in out Knowledge_Base; 288 On_Target : Targets_Set_Id; 289 Extra_Dirs : String := ""); 290 -- Find all compilers in "Extra_Dirs & $PATH". 291 -- Extra_Dirs should typically be the list of directories found in 292 -- --config command line arguments. 293 -- The only filtering done is the target, for optimization purposes (no 294 -- need to computed all info about the compiler if we know it will not be 295 -- uses anyway). 296 297 procedure Known_Compiler_Names 298 (Base : Knowledge_Base; 299 List : out Ada.Strings.Unbounded.Unbounded_String); 300 -- Set List to the comma-separated list of known compilers 301 302 procedure Generate_Configuration 303 (Base : Knowledge_Base; 304 Compilers : Compiler_Lists.List; 305 Output_File : String; 306 Target : String); 307 -- Generate the configuration file for the list of selected compilers 308 309 package String_Lists is 310 new Ada.Containers.Indefinite_Doubly_Linked_Lists (String); 311 312 procedure Put_Verbose (Str : String; Indent_Delta : Integer := 0); 313 -- Print Str if verbose mode is activated. 314 -- Indent_Delta will increase the current indentation level for all further 315 -- traces, which is used to highlight nested calls. Only the sign of 316 -- Indent_Delta is taken into account. 317 -- Nothing is printed if Str is the empty string, only the indentation is 318 -- changed 319 320 function Filter_Match 321 (Base : Knowledge_Base; 322 Comp : Compiler; 323 Filter : Compiler) return Boolean; 324 -- Returns True if Comp match Filter (the latter corresponds to a --config 325 -- command line argument). 326 327private 328 type Targets_Set_Id is range -1 .. Natural'Last; 329 330 All_Target_Sets : constant Targets_Set_Id := -1; 331 Unknown_Targets_Set : constant Targets_Set_Id := 0; 332 333 type Compiler is record 334 Name : Name_Id := No_Name; 335 -- The name of the compiler, as specified in the <name> node of the 336 -- knowledge base. If Compiler represents a filter as defined on through 337 -- --config switch, then name can also be the base name of the 338 -- executable we are looking for. In such a case, it never includes the 339 -- exec suffix (.exe on Windows) 340 341 Executable : Name_Id := No_Name; 342 Target : Name_Id := No_Name; 343 Targets_Set : Targets_Set_Id; 344 Path : Name_Id := No_Name; 345 346 Base_Name : Name_Id := No_Name; 347 -- Base name of the executable. This does not include the exec suffix 348 349 Version : Name_Id := No_Name; 350 Variables : Variables_Maps.Map; 351 Prefix : Name_Id := No_Name; 352 Runtime : Name_Id := No_Name; 353 Alt_Runtime : Name_Id := No_Name; 354 Runtime_Dir : Name_Id := No_Name; 355 Path_Order : Integer; 356 357 Language_Case : Name_Id := No_Name; 358 -- The supported language, with the casing read from the compiler. This 359 -- is for display purposes only 360 361 Language_LC : Name_Id := No_Name; 362 -- The supported language, always lower case 363 364 Selectable : Boolean := True; 365 Selected : Boolean := False; 366 Complete : Boolean := True; 367 end record; 368 369 No_Compiler : constant Compiler := 370 (Name => No_Name, 371 Target => No_Name, 372 Targets_Set => Unknown_Targets_Set, 373 Executable => No_Name, 374 Base_Name => No_Name, 375 Path => No_Name, 376 Variables => Variables_Maps.Empty_Map, 377 Version => No_Name, 378 Prefix => No_Name, 379 Runtime => No_Name, 380 Alt_Runtime => No_Name, 381 Runtime_Dir => No_Name, 382 Language_Case => No_Name, 383 Language_LC => No_Name, 384 Selectable => False, 385 Selected => False, 386 Complete => True, 387 Path_Order => 0); 388 389 type Pattern_Matcher_Access is access all GNAT.Regpat.Pattern_Matcher; 390 391 type External_Value_Type is (Value_Constant, 392 Value_Shell, 393 Value_Directory, 394 Value_Grep, 395 Value_Nogrep, 396 Value_Filter, 397 Value_Must_Match, 398 Value_Variable, 399 Value_Done); 400 type External_Value_Node 401 (Typ : External_Value_Type := Value_Constant) is 402 record 403 case Typ is 404 when Value_Constant => 405 Value : Name_Id; 406 when Value_Shell => 407 Command : Name_Id; 408 when Value_Directory => 409 Directory : Name_Id; 410 Directory_Group : Integer; 411 Dir_If_Match : Name_Id; 412 Contents : Pattern_Matcher_Access; 413 when Value_Grep => 414 Regexp_Re : Pattern_Matcher_Access; 415 Group : Natural; 416 when Value_Nogrep => 417 Regexp_No : Pattern_Matcher_Access; 418 when Value_Filter => 419 Filter : Name_Id; 420 when Value_Must_Match => 421 Must_Match : Name_Id; 422 when Value_Variable => 423 Var_Name : Name_Id; 424 when Value_Done => 425 null; 426 end case; 427 end record; 428 429 package External_Value_Nodes is 430 new Ada.Containers.Doubly_Linked_Lists (External_Value_Node); 431 432 subtype External_Value is External_Value_Nodes.List; 433 434 Null_External_Value : constant External_Value := 435 External_Value_Nodes.Empty_List; 436 437 type Compiler_Description is record 438 Name : Name_Id := No_Name; 439 Executable : Name_Id := No_Name; 440 Executable_Re : Pattern_Matcher_Access; 441 Prefix_Index : Integer := -1; 442 Target : External_Value; 443 Version : External_Value; 444 Variables : External_Value; 445 Languages : External_Value; 446 Runtimes : External_Value; 447 Default_Runtimes : String_Lists.List; 448 end record; 449 -- Executable_Re is only set if the name of the <executable> must be 450 -- taken as a regular expression. 451 452 package Compiler_Description_Maps is new 453 Ada.Containers.Indefinite_Hashed_Maps 454 (Name_Id, Compiler_Description, 455 Hash_Case_Insensitive, "="); 456 457 type Compiler_Filter is record 458 Name : Name_Id; 459 Version : Name_Id; 460 Version_Re : Pattern_Matcher_Access; 461 Runtime : Name_Id; 462 Runtime_Re : Pattern_Matcher_Access; 463 Language_LC : Name_Id; 464 end record; 465 -- Representation for a <compiler> node (in <configuration>) 466 467 package Compiler_Filter_Lists is new Ada.Containers.Doubly_Linked_Lists 468 (Compiler_Filter); 469 470 type Compilers_Filter is record 471 Compiler : Compiler_Filter_Lists.List; 472 Negate : Boolean := False; 473 end record; 474 475 No_Compilers_Filter : constant Compilers_Filter := 476 (Compiler => Compiler_Filter_Lists.Empty_List, 477 Negate => False); 478 -- a <compilers> filter, that matches if any of its <compiler> child 479 -- matches. 480 481 package Compilers_Filter_Lists is new Ada.Containers.Doubly_Linked_Lists 482 (Compilers_Filter); 483 484 type Configuration is record 485 Compilers_Filters : Compilers_Filter_Lists.List; 486 Targets_Filters : String_Lists.List; -- these are regexps 487 Negate_Targets : Boolean := False; 488 Config : Name_Id; 489 490 Supported : Boolean; 491 -- Whether the combination of compilers is supported 492 end record; 493 494 package Configuration_Lists is new Ada.Containers.Doubly_Linked_Lists 495 (Configuration); 496 497 package Target_Lists is new Ada.Containers.Doubly_Linked_Lists 498 (Pattern_Matcher_Access); 499 500 type Target_Set_Description is record 501 Name : Name_Id; 502 Patterns : Target_Lists.List; 503 end record; 504 505 subtype Known_Targets_Set_Id 506 is Targets_Set_Id range 1 .. Targets_Set_Id'Last; 507 -- Known targets set. They are in the base 508 509 package Targets_Set_Vectors is new Ada.Containers.Vectors 510 (Known_Targets_Set_Id, Target_Set_Description, "="); 511 512 type Knowledge_Base is record 513 Compilers : Compiler_Description_Maps.Map; 514 No_Compilers : String_Lists.List; 515 Check_Executable_Regexp : Boolean := False; 516 Configurations : Configuration_Lists.List; 517 Targets_Sets : Targets_Set_Vectors.Vector; 518 end record; 519 -- Check_Executable_Regexp is set to True if at least some of the 520 -- executable names are specified as regular expressions. In such a case, 521 -- a slightly slower algorithm is used to search for compilers. 522 -- No_Compilers is the list of languages that require no compiler, and thus 523 -- should not be searched on the PATH. 524 525end GprConfig.Knowledge; 526