PageRenderTime 33ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/tool/gec/src/gec.e

http://github.com/gobo-eiffel/gobo
Specman e | 945 lines | 749 code | 87 blank | 109 comment | 51 complexity | 9ad75625e8fa5f1559382814077e738a MD5 | raw file
  1. note
  2. description:
  3. "Gobo Eiffel Compiler"
  4. copyright: "Copyright (c) 2005-2021, Eric Bezault and others"
  5. license: "MIT License"
  6. date: "$Date$"
  7. revision: "$Revision$"
  8. class GEC
  9. inherit
  10. GEC_VERSION
  11. KL_SHARED_EXCEPTIONS
  12. KL_SHARED_ARGUMENTS
  13. KL_SHARED_EXECUTION_ENVIRONMENT
  14. KL_SHARED_STANDARD_FILES
  15. KL_SHARED_OPERATING_SYSTEM
  16. KL_SHARED_FILE_SYSTEM
  17. KL_IMPORTED_STRING_ROUTINES
  18. UC_SHARED_STRING_EQUALITY_TESTER
  19. export {NONE} all end
  20. UT_SHARED_ISE_VERSIONS
  21. export {NONE} all end
  22. ET_SHARED_ISE_VARIABLES
  23. export {NONE} all end
  24. ET_SHARED_TOKEN_CONSTANTS
  25. export {NONE} all end
  26. create
  27. execute,
  28. execute_with_arguments,
  29. execute_with_arguments_and_error_handler
  30. feature -- Execution
  31. execute
  32. -- Start 'gec' execution, reading arguments from the command-line.
  33. do
  34. execute_with_arguments (Arguments.to_array)
  35. Exceptions.die (exit_code)
  36. rescue
  37. Exceptions.die (4)
  38. end
  39. execute_with_arguments (a_args: ARRAY [STRING])
  40. -- Start 'gec' execution with arguments `a_args'.
  41. -- Set `exit_code'.
  42. require
  43. a_args_not_void: a_args /= Void
  44. no_void_arg: across a_args is l_arg all l_arg /= Void end
  45. local
  46. l_error_handler: ET_ERROR_HANDLER
  47. do
  48. create l_error_handler.make_standard
  49. execute_with_arguments_and_error_handler (a_args, l_error_handler)
  50. end
  51. execute_with_arguments_and_error_handler (a_args: ARRAY [STRING]; a_error_handler: ET_ERROR_HANDLER)
  52. -- Start 'gec' execution with arguments `a_args'.
  53. -- Set `exit_code'.
  54. require
  55. a_args_not_void: a_args /= Void
  56. no_void_arg: across a_args is l_arg all l_arg /= Void end
  57. a_error_handler_not_void: a_error_handler /= Void
  58. local
  59. a_filename: STRING
  60. a_file: KL_TEXT_INPUT_FILE
  61. do
  62. Arguments.set_program_name ("gec")
  63. -- For compatibility with ISE's tools, define the environment
  64. -- variable "$ISE_LIBRARY" to $ISE_EIFFEL" if not set yet.
  65. ise_variables.set_ise_library_variable
  66. -- Also define the environment variable "$ISE_PLATFORM" if not set yet.
  67. ise_variables.set_ise_platform_variable
  68. error_handler := a_error_handler
  69. parse_arguments (a_args)
  70. if exit_code = 0 and then not version_flag.was_found then
  71. a_filename := ecf_filename
  72. create a_file.make (a_filename)
  73. a_file.open_read
  74. if a_file.is_open_read then
  75. last_system := Void
  76. parse_ecf_file (a_file)
  77. a_file.close
  78. if attached last_system as l_last_system then
  79. process_system (l_last_system)
  80. debug ("stop")
  81. std.output.put_line ("Press Enter...")
  82. std.input.read_character
  83. end
  84. if exit_code = 0 and error_handler.has_error then
  85. exit_code := 2
  86. end
  87. else
  88. exit_code := 3
  89. end
  90. else
  91. report_cannot_read_error (a_filename)
  92. exit_code := 1
  93. end
  94. end
  95. rescue
  96. exit_code := 4
  97. end
  98. feature -- Access
  99. last_system: detachable ET_SYSTEM
  100. -- Last Eiffel system parsed, if any
  101. feature {NONE} -- Eiffel config file parsing
  102. parse_ecf_file (a_file: KI_CHARACTER_INPUT_STREAM)
  103. -- Read ECF file `a_file'.
  104. -- Put result in `last_system' if no error occurred.
  105. require
  106. a_file_not_void: a_file /= Void
  107. a_file_open_read: a_file.is_open_read
  108. local
  109. l_ecf_parser: ET_ECF_SYSTEM_PARSER
  110. l_ecf_error_handler: ET_ECF_ERROR_HANDLER
  111. l_override_settings: detachable ET_ECF_SETTINGS
  112. l_ecf_system: ET_ECF_SYSTEM
  113. l_target: ET_ECF_TARGET
  114. l_value: STRING
  115. do
  116. last_system := Void
  117. if is_silent then
  118. create l_ecf_error_handler.make_null
  119. else
  120. create l_ecf_error_handler.make_standard
  121. end
  122. create l_ecf_parser.make (l_ecf_error_handler)
  123. if is_finalize then
  124. l_override_settings := override_settings
  125. if l_override_settings = Void then
  126. create l_override_settings.make
  127. override_settings := l_override_settings
  128. end
  129. l_override_settings.set_primary_value ({ET_ECF_SETTING_NAMES}.finalize_setting_name, {ET_ECF_SETTING_NAMES}.true_setting_value)
  130. end
  131. l_ecf_parser.set_override_settings (override_settings)
  132. l_ecf_parser.set_override_capabilities (override_capabilities)
  133. l_ecf_parser.set_override_variables (override_variables)
  134. l_ecf_parser.parse_file (a_file, target_name)
  135. if not l_ecf_error_handler.has_error then
  136. l_ecf_system := l_ecf_parser.last_system
  137. if l_ecf_system /= Void then
  138. l_target := l_ecf_system.selected_target
  139. if l_target /= Void then
  140. l_value := l_target.variables.value ("gelint")
  141. if l_value /= Void and then l_value.is_boolean then
  142. ecf_gelint_option := l_value.to_boolean
  143. end
  144. end
  145. last_system := l_ecf_system
  146. end
  147. end
  148. end
  149. ecf_gelint_option: BOOLEAN
  150. -- Same as command-line option --gelint, but specified from the ECF file
  151. feature {NONE} -- Processing
  152. process_system (a_system: ET_SYSTEM)
  153. -- Process `a_system'.
  154. require
  155. a_system_not_void: a_system /= Void
  156. local
  157. l_system: ET_DYNAMIC_SYSTEM
  158. l_system_processor: ET_SYSTEM_PROCESSOR
  159. l_builder: ET_DYNAMIC_TYPE_SET_BUILDER
  160. l_root_type: ET_BASE_TYPE
  161. l_generator: ET_C_GENERATOR
  162. l_system_name: STRING
  163. l_thread_count: INTEGER
  164. dt_total: detachable DT_DATE_TIME
  165. dt2: detachable DT_DATE_TIME
  166. do
  167. error_handler.set_ise
  168. error_handler.set_verbose (is_verbose)
  169. l_thread_count := thread_count
  170. l_system_processor := {ET_SYSTEM_PROCESSOR_FACTORY}.new_system_processor (l_thread_count)
  171. l_system_processor.set_error_handler (error_handler)
  172. l_system_processor.set_ise_version (ise_version)
  173. l_system_processor.set_benchmark_shown (not is_no_benchmark and not is_silent)
  174. l_system_processor.set_nested_benchmark_shown (is_nested_benchmark and not is_no_benchmark and not is_silent)
  175. l_system_processor.set_metrics_shown (is_metrics and not is_silent)
  176. if is_gelint then
  177. l_system_processor.set_flat_mode (True)
  178. l_system_processor.set_flat_dbc_mode (True)
  179. end
  180. dt_total := l_system_processor.benchmark_start_time
  181. if l_thread_count > 1 then
  182. l_system_processor.compile (a_system)
  183. end
  184. create l_system.make (a_system, l_system_processor)
  185. if is_gelint then
  186. l_system.set_full_class_checking (True)
  187. end
  188. l_system.set_catcall_error_mode (catcall_error_mode)
  189. l_system.set_catcall_warning_mode (catcall_warning_mode)
  190. l_system.set_new_instance_types (new_instance_types)
  191. dt2 := l_system_processor.benchmark_start_time
  192. l_system_processor.set_benchmark_shown (False)
  193. create {ET_DYNAMIC_PUSH_TYPE_SET_BUILDER} l_builder.make (l_system, l_system_processor)
  194. l_system.set_dynamic_type_set_builder (l_builder)
  195. l_system.compile (l_system_processor)
  196. l_system_processor.set_benchmark_shown (not is_no_benchmark and not is_silent)
  197. l_system_processor.record_end_time (dt2, "Degree -2")
  198. l_root_type := a_system.root_type
  199. if l_root_type = Void then
  200. -- Do nothing.
  201. elseif l_root_type.same_named_type (a_system.none_type, tokens.unknown_class, tokens.unknown_class) then
  202. -- Do nothing.
  203. elseif l_system.has_fatal_error then
  204. exit_code := 1
  205. else
  206. -- C code generation.
  207. dt2 := l_system_processor.benchmark_start_time
  208. l_system_name := a_system.system_name
  209. if l_system_name = Void then
  210. l_system_name := l_root_type.base_class.lower_name
  211. end
  212. create l_generator.make (l_system, l_system_processor)
  213. if gc_option.was_found then
  214. -- Override any option that might have been specified
  215. -- in the Eiffel config file.
  216. l_generator.set_use_boehm_gc (use_boehm_gc)
  217. end
  218. l_generator.set_finalize_mode (is_finalize)
  219. l_generator.set_split_mode (not no_split)
  220. if split_size > 0 then
  221. l_generator.set_split_threshold (split_size)
  222. end
  223. l_generator.generate (l_system_name)
  224. if is_metrics and not is_silent then
  225. error_handler.info_file.put_string ("Type count: ")
  226. error_handler.info_file.put_integer (l_system.dynamic_types.count)
  227. error_handler.info_file.put_new_line
  228. error_handler.info_file.put_string ("Alive type count: ")
  229. error_handler.info_file.put_integer (l_system.alive_dynamic_type_count)
  230. error_handler.info_file.put_new_line
  231. error_handler.info_file.put_string ("Feature count: ")
  232. error_handler.info_file.put_integer (l_system.dynamic_feature_count)
  233. error_handler.info_file.put_new_line
  234. error_handler.info_file.put_string ("Dynamic type set count: ")
  235. error_handler.info_file.put_integer (l_builder.dynamic_type_set_count)
  236. error_handler.info_file.put_new_line
  237. error_handler.info_file.put_string ("Never void targets: ")
  238. error_handler.info_file.put_integer (l_generator.never_void_target_count)
  239. error_handler.info_file.put_new_line
  240. error_handler.info_file.put_string ("Can be void targets: ")
  241. error_handler.info_file.put_integer (l_generator.can_be_void_target_count)
  242. error_handler.info_file.put_new_line
  243. end
  244. l_system_processor.record_end_time (dt2, "Degree -3")
  245. if l_generator.has_fatal_error then
  246. exit_code := 1
  247. elseif not no_c_compile then
  248. dt2 := l_system_processor.benchmark_start_time
  249. compile_c_code (l_system_name)
  250. l_system_processor.record_end_time (dt2, "Degree -4")
  251. end
  252. end
  253. l_system_processor.record_end_time (dt_total, "Total Time")
  254. end
  255. compile_c_code (a_system_name: STRING)
  256. -- Compile generated C code.
  257. require
  258. a_system_name_not_void: a_system_name /= Void
  259. local
  260. l_command: KL_SHELL_COMMAND
  261. l_script_filename: STRING
  262. l_gecc: GECC
  263. l_exit_code: INTEGER
  264. do
  265. if operating_system.is_windows then
  266. l_script_filename := a_system_name + ".bat"
  267. else
  268. l_script_filename := a_system_name + ".sh"
  269. end
  270. if c_compile_using_script then
  271. create l_command.make (file_system.absolute_pathname (l_script_filename))
  272. l_command.execute
  273. l_exit_code := l_command.exit_code
  274. elseif c_compile_using_make then
  275. create l_command.make ("make -f " + a_system_name + ".make")
  276. l_command.execute
  277. l_exit_code := l_command.exit_code
  278. elseif c_compile_using_gecc then
  279. create l_command.make ("gecc --thread=" + thread_count.out + " " + l_script_filename)
  280. l_command.execute
  281. l_exit_code := l_command.exit_code
  282. else
  283. create l_gecc.execute_with_arguments (<<"--thread=" + thread_count.out, l_script_filename>>)
  284. l_exit_code := l_gecc.exit_code
  285. end
  286. if l_exit_code /= 0 then
  287. exit_code := 1
  288. end
  289. end
  290. feature -- Arguments
  291. ecf_filename: STRING
  292. -- Name of the ECF file
  293. target_name: detachable STRING
  294. -- Name of target to be used in ECF file.
  295. -- Use last target in ECF file if not specified.
  296. do
  297. if target_option.was_found then
  298. Result := target_option.parameter
  299. end
  300. end
  301. override_settings: detachable ET_ECF_SETTINGS
  302. -- Settings overriding those specified for the selected ECF target
  303. override_capabilities: detachable ET_ECF_CAPABILITIES
  304. -- Capabilities overriding those specified for the selected ECF target
  305. override_variables: detachable ET_ECF_VARIABLES
  306. -- Variables overriding those specified for the selected ECF target
  307. is_finalize: BOOLEAN
  308. -- Compilation with optimizations turned on?
  309. do
  310. Result := finalize_flag.was_found
  311. end
  312. is_gelint: BOOLEAN
  313. -- Should gelint be run on the full content of each class being compiled?
  314. do
  315. Result := gelint_flag.was_found or ecf_gelint_option
  316. end
  317. ise_version: UT_VERSION
  318. -- ISE version, whose semantics should be
  319. -- used by the Eiffel code analysis process
  320. catcall_error_mode: BOOLEAN
  321. -- Are CAT-call errors considered as fatal errors?
  322. do
  323. Result := catcall_option.was_found and then attached catcall_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "error")
  324. end
  325. catcall_warning_mode: BOOLEAN
  326. -- Are CAT-call errors considered just as warnings?
  327. do
  328. Result := not catcall_option.was_found or else attached catcall_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "warning")
  329. end
  330. new_instance_types: detachable DS_HASH_SET [STRING]
  331. -- Name of the types which can have instances created by 'TYPE.new_instance'
  332. -- or 'TYPE.new_special_any_instance'
  333. --
  334. -- Use all non-deferred, non-NONE, alive types if no types have been specified.
  335. no_c_compile: BOOLEAN
  336. -- Should the back-end C compiler not be invoked on the generated C code?
  337. do
  338. Result := c_compile_option.was_found and then attached c_compile_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "no")
  339. end
  340. c_compile_using_gecc: BOOLEAN
  341. -- Should the back-end C compiler be invoked on the generated C code using 'gecc'?
  342. do
  343. Result := c_compile_option.was_found and then attached c_compile_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "gecc")
  344. end
  345. c_compile_using_script: BOOLEAN
  346. -- Should the back-end C compiler be invoked on the generated C code using a script?
  347. do
  348. Result := c_compile_option.was_found and then attached c_compile_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "script")
  349. end
  350. c_compile_using_make: BOOLEAN
  351. -- Should the back-end C compiler be invoked on the generated C code using a makefile?
  352. do
  353. Result := c_compile_option.was_found and then attached c_compile_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "make")
  354. end
  355. no_split: BOOLEAN
  356. -- Should C code be generated into a single file?
  357. do
  358. Result := split_option.was_found and then not split_option.parameter
  359. end
  360. split_size: INTEGER
  361. -- Size (in bytes) of generated C files in bytes when in split mode
  362. use_boehm_gc: BOOLEAN
  363. -- Should the application be compiled with the Boehm GC?
  364. do
  365. Result := gc_option.was_found and then attached gc_option.parameter as l_parameter and then STRING_.same_string (l_parameter, "boehm")
  366. end
  367. thread_count: INTEGER
  368. -- Number of threads to be used
  369. do
  370. Result := {EXECUTION_ENVIRONMENT}.available_cpu_count.as_integer_32
  371. if thread_option.was_found then
  372. Result := thread_option.parameter
  373. if Result <= 0 then
  374. Result := {EXECUTION_ENVIRONMENT}.available_cpu_count.as_integer_32 + Result
  375. end
  376. end
  377. if Result < 1 or not {PLATFORM}.is_thread_capable then
  378. Result := 1
  379. end
  380. ensure
  381. thread_count_not_negative: Result >= 1
  382. end
  383. is_silent: BOOLEAN
  384. -- Should gec run in silent mode?
  385. do
  386. Result := silent_flag.was_found
  387. end
  388. is_no_benchmark: BOOLEAN
  389. -- Should no benchmark information be displayed?
  390. -- (default: display non-nested benchmark information)
  391. do
  392. Result := no_benchmark_flag.was_found
  393. end
  394. is_nested_benchmark: BOOLEAN
  395. -- Should nested benchmark information be displayed?
  396. do
  397. Result := nested_benchmark_flag.was_found
  398. end
  399. is_metrics: BOOLEAN
  400. -- Should metrics information be displayed?
  401. do
  402. Result := metrics_flag.was_found
  403. end
  404. is_verbose: BOOLEAN
  405. -- Should gec run in verbose mode?
  406. do
  407. Result := verbose_flag.was_found
  408. end
  409. feature -- Argument parsing
  410. target_option: AP_STRING_OPTION
  411. -- Option for '--target=<target_name>'
  412. setting_option: AP_STRING_OPTION
  413. -- Option for '--setting=name=value'
  414. capability_option: AP_STRING_OPTION
  415. -- Option for '--capability=name=value'
  416. variable_option: AP_STRING_OPTION
  417. -- Option for '--variable=FOO=BAR'
  418. catcall_option: AP_ENUMERATION_OPTION
  419. -- Option for '--catcall=<no|error|warning>'
  420. finalize_flag: AP_FLAG
  421. -- Flag for '--finalize'
  422. gelint_flag: AP_FLAG
  423. -- Flag for '--gelint'
  424. ise_option: AP_STRING_OPTION
  425. -- Option for '--ise=major[.minor[.revision[.build]]]'
  426. c_compile_option: AP_ENUMERATION_OPTION
  427. -- Option for '--cc=<no|script|make|gecc>'
  428. split_option: AP_BOOLEAN_OPTION
  429. -- Option for '--split=<no|yes>'
  430. split_size_option: AP_INTEGER_OPTION
  431. -- Option for '--split-size=<size>'
  432. gc_option: AP_ENUMERATION_OPTION
  433. -- Option for '--gc=<no|boehm>'
  434. new_instance_types_option: AP_STRING_OPTION
  435. -- Option for '--new-instance-types=<filename>'
  436. thread_option: AP_INTEGER_OPTION
  437. -- Option for '--thread=<thread_count>'
  438. nested_benchmark_flag: AP_FLAG
  439. -- Flag for '--nested-benchmark'
  440. no_benchmark_flag: AP_FLAG
  441. -- Flag for '--no-benchmark'
  442. metrics_flag: AP_FLAG
  443. -- Flag for '--metrics'
  444. silent_flag: AP_FLAG
  445. -- Flag for '--silent'
  446. verbose_flag: AP_FLAG
  447. -- Flag for '--verbose'
  448. version_flag: AP_FLAG
  449. -- Flag for '--version'
  450. parse_arguments (a_args: ARRAY [STRING])
  451. -- Initialize options and parse arguments `a_args'.
  452. require
  453. a_args_not_void: a_args /= Void
  454. no_void_arg: across a_args is l_arg all l_arg /= Void end
  455. local
  456. a_parser: AP_PARSER
  457. a_list: AP_ALTERNATIVE_OPTIONS_LIST
  458. do
  459. create a_parser.make
  460. a_parser.set_application_description ("Gobo Eiffel Compiler, translate Eiffel programs into C code.")
  461. a_parser.set_parameters_description ("ecf_filename")
  462. -- target.
  463. create target_option.make_with_long_form ("target")
  464. target_option.set_description ("Name of target to be used in ECF file. (default: last target in ECF file)")
  465. target_option.set_parameter_description ("target_name")
  466. a_parser.options.force_last (target_option)
  467. -- setting.
  468. create setting_option.make_with_long_form ("setting")
  469. setting_option.set_description ("Override settings defined in ECF file.")
  470. setting_option.set_parameter_description ("name=value")
  471. a_parser.options.force_last (setting_option)
  472. -- capability.
  473. create capability_option.make_with_long_form ("capability")
  474. capability_option.set_description ("Override capability usage defined in ECF file.")
  475. capability_option.set_parameter_description ("name=value")
  476. a_parser.options.force_last (capability_option)
  477. -- variable.
  478. create variable_option.make_with_long_form ("variable")
  479. variable_option.set_description ("Override variables defined in ECF file.")
  480. variable_option.set_parameter_description ("NAME=VALUE")
  481. a_parser.options.force_last (variable_option)
  482. -- finalize.
  483. create finalize_flag.make_with_long_form ("finalize")
  484. finalize_flag.set_description ("Compile with optimizations turned on.")
  485. a_parser.options.force_last (finalize_flag)
  486. -- gelint.
  487. create gelint_flag.make_with_long_form ("gelint")
  488. gelint_flag.set_description ("Run gelint on the full content of each class being compiled.")
  489. a_parser.options.force_last (gelint_flag)
  490. -- ise.
  491. create ise_option.make_with_long_form ("ise")
  492. ise_option.set_description ("Version of Eiffel whose semantics should be used during code analysis. (default: latest version)")
  493. ise_option.set_parameter_description ("major[.minor[.revision[.build]]]")
  494. ise_option.set_default_parameter (ise_latest.out)
  495. a_parser.options.force_last (ise_option)
  496. -- catcall
  497. create catcall_option.make_with_long_form ("catcall")
  498. catcall_option.set_description ("Should CAT-call errors be considered as fatal errors, as warnings, or just ignored? (default: warning)")
  499. catcall_option.extend ("no")
  500. catcall_option.extend ("error")
  501. catcall_option.extend ("warning")
  502. catcall_option.set_parameter_description ("no|error|warning")
  503. a_parser.options.force_last (catcall_option)
  504. -- cc
  505. create c_compile_option.make_with_long_form ("cc")
  506. c_compile_option.set_description ("Should the back-end C compiler be invoked on the generated C code, and if yes with what method? (default: gecc, built-in)")
  507. c_compile_option.extend ("no")
  508. c_compile_option.extend ("script")
  509. c_compile_option.extend ("make")
  510. c_compile_option.extend ("gecc")
  511. c_compile_option.set_parameter_description ("no|script|make|gecc")
  512. a_parser.options.force_last (c_compile_option)
  513. -- split
  514. create split_option.make_with_long_form ("split")
  515. split_option.set_description ("Should generated C code be split over several C files instead of being held in a single possibly large C file? (default: yes)")
  516. split_option.set_parameter_description ("no|yes")
  517. a_parser.options.force_last (split_option)
  518. -- split-size
  519. create split_size_option.make_with_long_form ("split-size")
  520. split_size_option.set_description ("Size of generated C files in bytes when in split mode. (default: 2,500,000)")
  521. split_size_option.set_parameter_description ("size")
  522. a_parser.options.force_last (split_size_option)
  523. -- new-instance-types
  524. create new_instance_types_option.make_with_long_form ("new-instance-types")
  525. new_instance_types_option.set_description ("File containing the list of types which can have instances created by 'TYPE.new_instance' or 'TYPE.new_special_any_instance'. (default: use all non-deferred, non-NONE, alive types)")
  526. new_instance_types_option.set_parameter_description ("filename")
  527. a_parser.options.force_last (new_instance_types_option)
  528. -- gc
  529. create gc_option.make_with_long_form ("gc")
  530. gc_option.set_description ("Which garbage collector should the application be compiled with? (default: no)")
  531. gc_option.extend ("no")
  532. gc_option.extend ("boehm")
  533. gc_option.set_parameter_description ("no|boehm")
  534. a_parser.options.force_last (gc_option)
  535. -- thread
  536. create thread_option.make_with_long_form ("thread")
  537. thread_option.set_description ("Number of threads to be used. Negative numbers -N mean %"number of CPUs - N%". (default: number of CPUs)")
  538. thread_option.set_parameter_description ("thread_count")
  539. if {PLATFORM}.is_thread_capable then
  540. a_parser.options.force_last (thread_option)
  541. end
  542. -- silent
  543. create silent_flag.make_with_long_form ("silent")
  544. silent_flag.set_description ("Run gec in silent mode.")
  545. a_parser.options.force_last (silent_flag)
  546. -- no-benchmark.
  547. create no_benchmark_flag.make_with_long_form ("no-benchmark")
  548. no_benchmark_flag.set_description ("Should no benchmark information be displayed? (default: display non-nested benchmark information)")
  549. a_parser.options.force_last (no_benchmark_flag)
  550. -- nested-benchmark.
  551. create nested_benchmark_flag.make_with_long_form ("nested-benchmark")
  552. nested_benchmark_flag.set_description ("Should nested benchmark information be displayed?")
  553. a_parser.options.force_last (nested_benchmark_flag)
  554. -- metrics.
  555. create metrics_flag.make_with_long_form ("metrics")
  556. metrics_flag.set_description ("Should metrics information be displayed?")
  557. a_parser.options.force_last (metrics_flag)
  558. -- verbose
  559. create verbose_flag.make_with_long_form ("verbose")
  560. verbose_flag.set_description ("Run gec in verbose mode.")
  561. a_parser.options.force_last (verbose_flag)
  562. -- version
  563. create version_flag.make ('V', "version")
  564. version_flag.set_description ("Print the version number of gec and exit.")
  565. create a_list.make (version_flag)
  566. a_parser.alternative_options_lists.force_last (a_list)
  567. -- Parsing.
  568. a_parser.parse_array (a_args)
  569. if silent_flag.was_found then
  570. create {ET_NULL_ERROR_HANDLER} error_handler.make_null
  571. end
  572. if version_flag.was_found then
  573. report_version_number
  574. ecf_filename := ""
  575. ise_version := ise_latest
  576. exit_code := 0
  577. elseif a_parser.parameters.count /= 1 then
  578. report_usage_message (a_parser)
  579. ecf_filename := ""
  580. ise_version := ise_latest
  581. exit_code := 1
  582. else
  583. ecf_filename := a_parser.parameters.first
  584. set_ise_version (ise_option, a_parser)
  585. set_override_settings (setting_option, a_parser)
  586. set_override_capabilities (capability_option, a_parser)
  587. set_override_variables (variable_option, a_parser)
  588. set_split_size (split_size_option, a_parser)
  589. set_new_instance_types (new_instance_types_option, a_parser)
  590. end
  591. ensure
  592. ecf_filename_not_void: ecf_filename /= Void
  593. target_option_not_void: target_option /= Void
  594. setting_option_not_void: setting_option /= Void
  595. capability_option_not_void: capability_option /= Void
  596. variable_option_not_void: variable_option /= Void
  597. catcall_option_not_void: catcall_option /= Void
  598. finalize_flag_not_void: finalize_flag /= Void
  599. silent_flag_not_void: silent_flag /= Void
  600. no_benchmark_flag_not_void: no_benchmark_flag /= Void
  601. nested_benchmark_flag_not_void: nested_benchmark_flag /= Void
  602. metrics_flag_not_void: metrics_flag /= Void
  603. verbose_flag_not_void: verbose_flag /= Void
  604. version_flag_not_void: version_flag /= Void
  605. c_compile_option_not_void: c_compile_option /= Void
  606. split_option_not_void: split_option /= Void
  607. split_size_option_not_void: split_size_option /= Void
  608. gc_option_not_void: gc_option /= Void
  609. thread_option_not_void: thread_option /= Void
  610. new_instance_types_option_not_void: new_instance_types_option /= Void
  611. end
  612. set_ise_version (a_option: like ise_option; a_parser: AP_PARSER)
  613. -- Set `ise_version' with information passed in `a_option'.
  614. -- Report usage message and exit in case of invalid input.
  615. require
  616. a_option_not_void: a_option /= Void
  617. a_parser_not_void: a_parser /= Void
  618. local
  619. l_ise_regexp: RX_PCRE_REGULAR_EXPRESSION
  620. l_ise_version: detachable UT_VERSION
  621. do
  622. l_ise_version := ise_latest
  623. if not attached a_option.parameter as l_parameter then
  624. report_usage_message (a_parser)
  625. exit_code := 1
  626. elseif not STRING_.same_string (l_parameter, ise_latest.out) then
  627. create l_ise_regexp.make
  628. l_ise_regexp.compile ("([0-9]+)(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?")
  629. if l_ise_regexp.recognizes (l_parameter) then
  630. inspect l_ise_regexp.match_count
  631. when 2 then
  632. create l_ise_version.make_major (l_ise_regexp.captured_substring (1).to_integer)
  633. when 4 then
  634. create l_ise_version.make_major_minor (l_ise_regexp.captured_substring (1).to_integer, l_ise_regexp.captured_substring (3).to_integer)
  635. when 6 then
  636. create l_ise_version.make (l_ise_regexp.captured_substring (1).to_integer, l_ise_regexp.captured_substring (3).to_integer, l_ise_regexp.captured_substring (5).to_integer, 0)
  637. when 8 then
  638. create l_ise_version.make (l_ise_regexp.captured_substring (1).to_integer, l_ise_regexp.captured_substring (3).to_integer, l_ise_regexp.captured_substring (5).to_integer, l_ise_regexp.captured_substring (7).to_integer)
  639. else
  640. report_usage_message (a_parser)
  641. exit_code := 1
  642. end
  643. else
  644. report_usage_message (a_parser)
  645. exit_code := 1
  646. end
  647. end
  648. ise_version := l_ise_version
  649. end
  650. set_override_settings (a_option: like setting_option; a_parser: AP_PARSER)
  651. -- Set `override_settings' with information passed in `a_option'.
  652. -- Report usage message and exit in case of invalid input.
  653. require
  654. a_option_not_void: a_option /= Void
  655. a_parser_not_void: a_parser /= Void
  656. local
  657. l_override_settings: detachable ET_ECF_SETTINGS
  658. l_definition: STRING
  659. l_index: INTEGER
  660. do
  661. if not a_option.parameters.is_empty then
  662. create l_override_settings.make
  663. across a_option.parameters as l_settings loop
  664. if attached l_settings.item as l_setting then
  665. l_definition := l_setting
  666. if l_definition.count > 0 then
  667. l_index := l_definition.index_of ('=', 1)
  668. if l_index = 0 then
  669. l_override_settings.set_primary_value (l_definition, "")
  670. elseif l_index = l_definition.count then
  671. l_override_settings.set_primary_value (l_definition.substring (1, l_index - 1), "")
  672. elseif l_index /= 1 then
  673. l_override_settings.set_primary_value (l_definition.substring (1, l_index - 1), l_definition.substring (l_index + 1, l_definition.count))
  674. end
  675. end
  676. end
  677. end
  678. end
  679. override_settings := l_override_settings
  680. end
  681. set_override_capabilities (a_option: like capability_option; a_parser: AP_PARSER)
  682. -- Set `override_capabilities' with information passed in `a_option'.
  683. -- Report usage message and exit in case of invalid input.
  684. require
  685. a_option_not_void: a_option /= Void
  686. a_parser_not_void: a_parser /= Void
  687. local
  688. l_override_capabilities: detachable ET_ECF_CAPABILITIES
  689. l_definition: STRING
  690. l_index: INTEGER
  691. do
  692. if not a_option.parameters.is_empty then
  693. create l_override_capabilities.make
  694. across a_option.parameters as l_capabilities loop
  695. if attached l_capabilities.item as l_capability then
  696. l_definition := l_capability
  697. if l_definition.count > 0 then
  698. l_index := l_definition.index_of ('=', 1)
  699. if l_index = 0 then
  700. l_override_capabilities.set_primary_use_value (l_definition, "")
  701. elseif l_index = l_definition.count then
  702. l_override_capabilities.set_primary_use_value (l_definition.substring (1, l_index - 1), "")
  703. elseif l_index /= 1 then
  704. l_override_capabilities.set_primary_use_value (l_definition.substring (1, l_index - 1), l_definition.substring (l_index + 1, l_definition.count))
  705. end
  706. end
  707. end
  708. end
  709. end
  710. override_capabilities := l_override_capabilities
  711. end
  712. set_override_variables (a_option: like variable_option; a_parser: AP_PARSER)
  713. -- Set `override_variables' with information passed in `a_option'.
  714. -- Report usage message and exit in case of invalid input.
  715. require
  716. a_option_not_void: a_option /= Void
  717. a_parser_not_void: a_parser /= Void
  718. local
  719. l_override_variables: ET_ECF_VARIABLES
  720. l_definition: STRING
  721. l_index: INTEGER
  722. do
  723. create l_override_variables.make
  724. l_override_variables.set_primary_value ("GOBO_EIFFEL", "ge")
  725. Execution_environment.set_variable_value ("GOBO_EIFFEL", "ge")
  726. if not a_option.parameters.is_empty then
  727. across a_option.parameters as l_variables loop
  728. if attached l_variables.item as l_variable then
  729. l_definition := l_variable
  730. if l_definition.count > 0 then
  731. l_index := l_definition.index_of ('=', 1)
  732. if l_index = 0 then
  733. l_override_variables.set_primary_value (l_definition, "")
  734. elseif l_index = l_definition.count then
  735. l_override_variables.set_primary_value (l_definition.substring (1, l_index - 1), "")
  736. elseif l_index /= 1 then
  737. l_override_variables.set_primary_value (l_definition.substring (1, l_index - 1), l_definition.substring (l_index + 1, l_definition.count))
  738. end
  739. end
  740. end
  741. end
  742. end
  743. override_variables := l_override_variables
  744. end
  745. set_split_size (a_option: like split_size_option; a_parser: AP_PARSER)
  746. -- Set `split_size' with information passed in `a_option'.
  747. -- Report usage message and exit in case of invalid input.
  748. require
  749. a_option_not_void: a_option /= Void
  750. a_parser_not_void: a_parser /= Void
  751. local
  752. l_error: AP_ERROR
  753. do
  754. if a_option.was_found then
  755. if a_option.parameter > 0 then
  756. split_size := a_option.parameter
  757. else
  758. create l_error.make_invalid_parameter_error (a_option, a_option.parameter.out)
  759. error_handler.report_error (l_error)
  760. exit_code := 1
  761. end
  762. end
  763. end
  764. set_new_instance_types (a_option: like new_instance_types_option; a_parser: AP_PARSER)
  765. -- Set `new_instance_types' with information passed in `a_option'.
  766. -- Report usage message and exit in case of invalid input.
  767. require
  768. a_option_not_void: a_option /= Void
  769. a_parser_not_void: a_parser /= Void
  770. local
  771. l_new_instance_types: DS_HASH_SET [STRING]
  772. l_file: KL_TEXT_INPUT_FILE
  773. s: STRING
  774. do
  775. if a_option.was_found and then attached a_option.parameter as l_filename then
  776. create l_file.make (l_filename)
  777. l_file.open_read
  778. if l_file.is_open_read then
  779. create l_new_instance_types.make_equal (100)
  780. new_instance_types := l_new_instance_types
  781. from
  782. l_file.read_line
  783. until
  784. l_file.end_of_file
  785. loop
  786. s := l_file.last_string.twin
  787. s.adjust
  788. if not s.is_empty and not s.starts_with ("--") then
  789. l_new_instance_types.force (s)
  790. end
  791. l_file.read_line
  792. end
  793. l_file.close
  794. else
  795. report_cannot_read_error (l_filename)
  796. exit_code := 1
  797. end
  798. end
  799. end
  800. feature -- Error handling
  801. error_handler: ET_ERROR_HANDLER
  802. -- Error handler
  803. report_cannot_read_error (a_filename: STRING)
  804. -- Report that `a_filename' cannot be
  805. -- opened in read mode.
  806. require
  807. a_filename_not_void: a_filename /= Void
  808. local
  809. an_error: UT_CANNOT_READ_FILE_ERROR
  810. do
  811. create an_error.make (a_filename)
  812. error_handler.report_error (an_error)
  813. end
  814. report_version_number
  815. -- Report version number.
  816. local
  817. a_message: UT_VERSION_NUMBER
  818. do
  819. create a_message.make (Version_number)
  820. error_handler.report_info (a_message)
  821. end
  822. report_usage_message (a_parser: AP_PARSER)
  823. -- Report usage message.
  824. require
  825. a_parser_not_void: a_parser /= Void
  826. local
  827. l_error: UT_MESSAGE
  828. do
  829. create l_error.make (a_parser.full_usage_instruction)
  830. error_handler.report_error (l_error)
  831. end
  832. exit_code: INTEGER
  833. -- Exit code
  834. invariant
  835. error_handler_not_void: error_handler /= Void
  836. ecf_filename_not_void: ecf_filename /= Void
  837. ise_version_not_void: ise_version /= Void
  838. target_option_not_void: target_option /= Void
  839. setting_option_not_void: setting_option /= Void
  840. capability_option_not_void: capability_option /= Void
  841. variable_option_not_void: variable_option /= Void
  842. catcall_option_not_void: catcall_option /= Void
  843. gelint_flag_not_void: gelint_flag /= Void
  844. ise_option_not_void: ise_option /= Void
  845. finalize_flag_not_void: finalize_flag /= Void
  846. silent_flag_not_void: silent_flag /= Void
  847. no_benchmark_flag_not_void: no_benchmark_flag /= Void
  848. nested_benchmark_flag_not_void: nested_benchmark_flag /= Void
  849. metrics_flag_not_void: metrics_flag /= Void
  850. verbose_flag_not_void: verbose_flag /= Void
  851. version_flag_not_void: version_flag /= Void
  852. c_compile_option_not_void: c_compile_option /= Void
  853. split_option_not_void: split_option /= Void
  854. split_size_option_not_void: split_size_option /= Void
  855. new_instance_types_option_not_void: new_instance_types_option /= Void
  856. gc_option_not_void: gc_option /= Void
  857. thread_option_not_void: thread_option /= Void
  858. end