PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/tool/geant/src/geant_project.e

http://github.com/gobo-eiffel/gobo
Specman e | 669 lines | 518 code | 78 blank | 73 comment | 32 complexity | 6eb585e9731ee626a35cc63d2945f141 MD5 | raw file
  1. note
  2. description:
  3. "Contents of geant project files"
  4. library: "Gobo Eiffel Ant"
  5. copyright: "Copyright (c) 2001-2018, Sven Ehrke and others"
  6. license: "MIT License"
  7. date: "$Date$"
  8. revision: "$Revision$"
  9. class GEANT_PROJECT
  10. inherit
  11. ANY
  12. KL_SHARED_ARGUMENTS
  13. export {NONE} all end
  14. KL_SHARED_EXCEPTIONS
  15. export {NONE} all end
  16. GEANT_SHARED_PROPERTIES
  17. export {NONE} all end
  18. create
  19. make
  20. feature {NONE} -- Initialization
  21. make (a_variables: GEANT_PROJECT_VARIABLES; a_options: GEANT_PROJECT_OPTIONS; a_name: STRING)
  22. -- Create a new project.
  23. require
  24. a_variables_not_void: a_variables /= Void
  25. a_options_not_void: a_options /= Void
  26. a_name_not_void: a_name /= Void
  27. a_name_not_empty: not a_name.is_empty
  28. local
  29. a_tester: UC_STRING_EQUALITY_TESTER
  30. do
  31. name := a_name
  32. output_file := std.output
  33. set_variables (a_variables)
  34. set_options (a_options)
  35. create selected_targets.make_map (5)
  36. create a_tester
  37. selected_targets.set_key_equality_tester (a_tester)
  38. create {DS_ARRAYED_STACK [GEANT_TARGET]} targets_stack.make (10)
  39. create task_factory.make (Current)
  40. build_successful := True
  41. ensure
  42. variables_set: variables = a_variables
  43. options_set: options = a_options
  44. selected_targets_not_void: selected_targets /= Void
  45. name_set: name = a_name
  46. end
  47. feature -- Access
  48. name: STRING
  49. -- Name of project
  50. start_target_name: detachable STRING
  51. -- Name of first target to be built
  52. description: detachable STRING
  53. -- Project description
  54. variables: GEANT_PROJECT_VARIABLES
  55. -- Project variables
  56. aggregated_variables_array: ARRAY [GEANT_VARIABLES]
  57. -- Array of available variables sets
  58. -- i.e: arguments, locals, variables
  59. do
  60. Result := <<target_arguments_stack.item, target_locals_stack.item, variables>>
  61. ensure
  62. Result_not_void: Result /= Void
  63. end
  64. options: GEANT_PROJECT_OPTIONS
  65. -- Project options
  66. targets: detachable DS_HASH_TABLE [GEANT_TARGET, STRING]
  67. -- Immediate targets
  68. selected_targets: DS_HASH_TABLE [GEANT_TARGET, STRING]
  69. -- Targets selected in heir
  70. preferred_start_target: detachable GEANT_TARGET
  71. -- Preferred target to start build process
  72. do
  73. if attached start_target_name as l_start_target_name and then l_start_target_name.count > 0 then
  74. if attached targets as l_targets then
  75. if l_targets.has (l_start_target_name) then
  76. Result := l_targets.item (l_start_target_name)
  77. end
  78. end
  79. end
  80. end
  81. default_target: detachable GEANT_TARGET
  82. -- Target to start build process in case `preferred_start_target' is Void
  83. do
  84. if attached default_target_name as l_default_target_name and then l_default_target_name.count > 0 then
  85. if attached targets as l_targets then
  86. if l_targets.has (l_default_target_name) then
  87. Result := l_targets.item (l_default_target_name)
  88. end
  89. end
  90. end
  91. end
  92. start_target: GEANT_TARGET
  93. -- `preferred_start_target' if not Void; `default_target' otherwise
  94. do
  95. Result := default_target
  96. if attached start_target_name as l_start_target_name and then l_start_target_name.count > 0 then
  97. if not attached preferred_start_target as l_preferred_start_target then
  98. exit_application (1, <<"Cannot determine start target `", l_start_target_name + "%'">>)
  99. else
  100. Result := l_preferred_start_target
  101. end
  102. end
  103. if Result = Void then
  104. exit_application (1, <<"Cannot determine start target.">>)
  105. check exited: False then end
  106. end
  107. ensure
  108. start_target_not_void: Result /= Void
  109. end
  110. build_successful: BOOLEAN
  111. -- Was last build successful?
  112. inherit_clause: detachable GEANT_INHERIT
  113. -- Inherit clause
  114. old_inherit: BOOLEAN
  115. -- Was current defined via old inheritance mechanism?
  116. -- TODO: remove after obsolete period
  117. target_name (a_target: GEANT_TARGET): STRING
  118. -- Name of target `a_target' within context of current project
  119. require
  120. a_target_not_void: a_target /= Void
  121. targets_not_void: attached targets as l_targets
  122. has_target: l_targets.has_item (a_target)
  123. local
  124. a_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
  125. do
  126. check precondition: attached targets as l_targets then
  127. Result := ""
  128. a_cursor := l_targets.new_cursor
  129. from a_cursor.start until a_cursor.after loop
  130. if a_target = a_cursor.item then
  131. Result := a_cursor.key
  132. a_cursor.go_after -- Jump out of the loop.
  133. else
  134. a_cursor.forth
  135. end
  136. end
  137. end
  138. ensure
  139. target_name_not_void: Result /= Void
  140. target_name_not_empty: Result.count > 0
  141. end
  142. default_target_name: detachable STRING
  143. -- Name of default target if set
  144. position_table: detachable XM_POSITION_TABLE
  145. -- Position table for XM_NODES
  146. feature -- Status report
  147. has_parent_with_name (a_name: STRING): BOOLEAN
  148. -- Does current project have a parent project named `a_name'?
  149. local
  150. i, nb: INTEGER
  151. a_parent_project: GEANT_PROJECT
  152. a_parents: DS_ARRAYED_LIST [GEANT_PARENT]
  153. do
  154. if attached inherit_clause as l_inherit_clause then
  155. a_parents := l_inherit_clause.parents
  156. nb := a_parents.count
  157. from i := 1 until i > nb loop
  158. a_parent_project := a_parents.item (i).parent_project
  159. if a_parent_project /= Void then
  160. if STRING_.same_string (a_parent_project.name, a_name) then
  161. Result := True
  162. i := nb + 1 -- Jump out of the loop.
  163. elseif a_parent_project.has_parent_with_name (a_name) then
  164. Result := True
  165. i := nb + 1 -- Jump out of the loop.
  166. end
  167. end
  168. i := i + 1
  169. end
  170. end
  171. end
  172. is_builtin_variable_name (a_name: STRING): BOOLEAN
  173. -- Is `a_name' the name of a built-in variable?
  174. require
  175. a_name_not_void: a_name /= Void
  176. a_name_not_empty: a_name.count > 0
  177. do
  178. Result := variables.is_builtin_variable_name (a_name)
  179. -- Check also buildscript specific built-in variables (see `GEANT_PROJECT_ELEMENT.make'):
  180. Result := Result or else STRING_.same_string (STRING_.concat (name, ".absdir"), a_name)
  181. Result := Result or else STRING_.same_string (STRING_.concat (name, ".dir"), a_name)
  182. Result := Result or else STRING_.same_string (STRING_.concat (name, ".filename"), a_name)
  183. end
  184. feature -- Setting
  185. set_description (a_description: STRING)
  186. -- Set `description' to `a_description'.
  187. require
  188. a_description_not_void: a_description /= Void
  189. a_description_not_empty: a_description.count > 0
  190. do
  191. description := a_description
  192. ensure
  193. description_set: description = a_description
  194. end
  195. set_name (a_name: STRING)
  196. -- Set `name' to `a_name'.
  197. require
  198. a_name_not_void: a_name /= Void
  199. a_name_not_empty: a_name.count > 0
  200. do
  201. name := a_name
  202. ensure
  203. name_set: name = a_name
  204. end
  205. set_start_target_name (a_start_target_name: STRING)
  206. -- Set `start_target_name' to `a_start_target_name'.
  207. require
  208. a_start_target_name_not_void: a_start_target_name /= Void
  209. a_start_target_name_not_empty: a_start_target_name.count > 0
  210. targets_has_a_start_target_name: attached targets as l_targets and then l_targets.has (a_start_target_name)
  211. do
  212. start_target_name := a_start_target_name
  213. ensure
  214. start_target_name_set: start_target_name = a_start_target_name
  215. end
  216. set_default_target_name (a_default_target_name: STRING)
  217. -- Set `default_target_name' to `a_default_target_name'.
  218. require
  219. a_default_target_name_not_void: a_default_target_name /= Void
  220. a_default_target_name_not_empty: a_default_target_name.count > 0
  221. do
  222. default_target_name := a_default_target_name
  223. ensure
  224. default_target_name_set: default_target_name = a_default_target_name
  225. end
  226. set_targets (a_targets: like targets)
  227. -- Set `targets' to `a_targets'.
  228. require
  229. a_targets_not_void: a_targets /= Void
  230. do
  231. targets := a_targets
  232. ensure
  233. targets_set: targets = a_targets
  234. end
  235. set_variables (a_variables: like variables)
  236. -- Set `variables' to `a_variables'.
  237. require
  238. a_variables_not_void: a_variables /= Void
  239. do
  240. variables := a_variables
  241. ensure
  242. variables_set: variables = a_variables
  243. end
  244. set_options (a_options: like options)
  245. -- Set `options' to `a_options'.
  246. require
  247. a_options_not_void: a_options /= Void
  248. do
  249. options := a_options
  250. ensure
  251. options_set: options = a_options
  252. end
  253. set_inherit_clause (a_inherit_clause: like inherit_clause)
  254. -- Set `inherit_clause' to `a_inherit_clause'.
  255. require
  256. a_inherit_clause_not_void: a_inherit_clause /= Void
  257. do
  258. inherit_clause := a_inherit_clause
  259. ensure
  260. inherit_clause_set: inherit_clause = a_inherit_clause
  261. end
  262. set_old_inherit (a_old_inherit: BOOLEAN)
  263. -- Set `old_inherit' to `a_old_inherit'.
  264. -- TODO: remove after obsolete period
  265. do
  266. old_inherit := a_old_inherit
  267. ensure
  268. old_inherit_set: old_inherit = a_old_inherit
  269. end
  270. set_position_table (a_position_table: like position_table)
  271. -- Set `position_table' to `a_position_table'.
  272. require
  273. a_position_table_not_void: a_position_table /= Void
  274. do
  275. position_table := a_position_table
  276. ensure
  277. position_table_set: position_table = a_position_table
  278. end
  279. feature {GEANT_GROUP, GEANT_TARGET} -- Task factory
  280. new_task (a_xml_element: XM_ELEMENT): detachable GEANT_TASK
  281. -- New GEANT_TASK for `a_xml_element'
  282. do
  283. if attached task_factory as l_task_factory then
  284. Result := l_task_factory.new_task (a_xml_element)
  285. end
  286. end
  287. task_factory: detachable GEANT_TASK_FACTORY
  288. -- Task factory associated to Current
  289. feature -- Processing
  290. merge_in_parent_projects
  291. -- Load parent projects if present.
  292. local
  293. a_parent: GEANT_PARENT
  294. a_parent_cursor: DS_LINEAR_CURSOR [GEANT_PARENT]
  295. a_target: GEANT_TARGET
  296. a_target_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
  297. do
  298. -- Handle inherit_clause:
  299. if attached inherit_clause as l_inherit_clause then
  300. -- Prepare parent projects:
  301. a_parent_cursor := l_inherit_clause.parents.new_cursor
  302. from a_parent_cursor.start until a_parent_cursor.after loop
  303. a_parent := a_parent_cursor.item
  304. check parents_parent_project_not_void: a_parent.parent_project /= Void end
  305. a_parent.prepare_project
  306. a_parent_cursor.forth
  307. end
  308. -- Merge parent projects:
  309. a_parent_cursor := l_inherit_clause.parents.new_cursor
  310. from a_parent_cursor.start until a_parent_cursor.after loop
  311. a_parent := a_parent_cursor.item
  312. l_inherit_clause.merge_in_parent_project (a_parent)
  313. a_parent_cursor.forth
  314. end
  315. l_inherit_clause.apply_selects
  316. -- List all targets:
  317. if attached targets as l_targets then
  318. from
  319. a_target_cursor := l_targets.new_cursor
  320. a_target_cursor.start
  321. trace_debug (<<"Project '", name, "': target list:">>)
  322. until
  323. a_target_cursor.after
  324. loop
  325. a_target := a_target_cursor.item
  326. trace_debug (<<" target `", a_target_cursor.key, "' (", a_target.full_name, ")">>)
  327. a_target.show_precursors
  328. a_target_cursor.forth
  329. end
  330. end
  331. end
  332. end
  333. calculate_depend_order (a_depend_targets: DS_ARRAYED_STACK [GEANT_TARGET])
  334. -- Setup `build_targets' according to target dependencies.
  335. require
  336. loaded: targets /= Void
  337. depend_targets_not_void: a_depend_targets /= Void
  338. local
  339. a_target: GEANT_TARGET
  340. a_tmp_dependent_targets: DS_ARRAYED_STACK [GEANT_TARGET]
  341. do
  342. -- Get dependent targets:
  343. a_target := a_depend_targets.item
  344. trace_debug (<<"pushing target: ", a_target.name>>)
  345. a_tmp_dependent_targets := a_target.dependent_targets
  346. -- Add all dependent targets to `build_targets':
  347. from until a_tmp_dependent_targets.count = 0 loop
  348. a_depend_targets.force (a_tmp_dependent_targets.item)
  349. a_tmp_dependent_targets.remove
  350. -- Recursive call of routine for dependent target:
  351. calculate_depend_order (a_depend_targets)
  352. end
  353. end
  354. build (a_arguments: GEANT_ARGUMENT_VARIABLES)
  355. -- Build project: execute project's tasks.
  356. require
  357. targets_not_void: targets /= Void
  358. a_arguments_not_void: a_arguments /= Void
  359. local
  360. a_target: GEANT_TARGET
  361. do
  362. trace (<<"Building Project">>)
  363. a_target := start_target
  364. build_target (a_target, a_arguments)
  365. end
  366. show_target_info
  367. -- Print list of name and description for all targets of project.
  368. require
  369. targets_not_void: targets /= Void
  370. local
  371. a_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
  372. a_target: GEANT_TARGET
  373. do
  374. check precondition: attached targets as l_targets then
  375. a_cursor := l_targets.new_cursor
  376. from a_cursor.start until a_cursor.after loop
  377. a_target := a_cursor.item
  378. if a_target.is_exported_to_any then
  379. output_file.put_line (a_target.full_name)
  380. if attached a_target.obsolete_message as l_obsolete_message then
  381. output_file.put_line (" obsolete. " + l_obsolete_message)
  382. end
  383. output_file.put_line (" " + a_target.description)
  384. end
  385. a_cursor.forth
  386. end
  387. end
  388. end
  389. build_target (a_target: GEANT_TARGET; a_arguments: GEANT_ARGUMENT_VARIABLES)
  390. -- Analyze dependencies and execute `a_target'.
  391. require
  392. a_target_not_void: a_target /= Void
  393. a_arguments_not_void: a_arguments /= Void
  394. local
  395. depend_targets: DS_ARRAYED_STACK [GEANT_TARGET]
  396. depend_arguments: GEANT_ARGUMENT_VARIABLES
  397. do
  398. target_arguments_stack.force (a_arguments)
  399. -- Analyze dependencies of targets:
  400. create depend_targets.make (10)
  401. depend_targets.force (a_target)
  402. calculate_depend_order (depend_targets)
  403. -- Execute depend targets (use empty arguments since depend does not support argument passing):
  404. create depend_arguments.make
  405. target_arguments_stack.force (depend_arguments)
  406. from until depend_targets.count = 1 loop
  407. execute_target (depend_targets.item, depend_arguments, False, True)
  408. depend_targets.remove
  409. end
  410. target_arguments_stack.remove
  411. -- Execute `a_target':
  412. check last_target: depend_targets.item = a_target end
  413. execute_target (a_target, a_arguments, True, True)
  414. target_arguments_stack.remove
  415. end
  416. execute_target (a_target: GEANT_TARGET; a_arguments: GEANT_ARGUMENT_VARIABLES; a_force: BOOLEAN; a_polymorph: BOOLEAN)
  417. -- Execute `a_target' if not executed before;
  418. -- Execute anyway if `a_force' is True.
  419. require
  420. target_not_void: a_target /= Void
  421. a_arguments_not_void: a_arguments /= Void
  422. local
  423. old_current_target: like current_target
  424. a_execute_target: like current_target
  425. do
  426. trace_debug (<<"project '", name, "': executing target `", a_target.full_name, "%'">>)
  427. old_current_target := current_target
  428. if a_force or else not a_target.is_executed then
  429. -- Handle polymorphic calls:
  430. if a_polymorph then
  431. a_execute_target := a_target.final_target
  432. else
  433. a_execute_target := a_target
  434. end
  435. targets_stack.force (a_execute_target)
  436. target_locals_stack.force (create {GEANT_VARIABLES}.make)
  437. check current_target = a_execute_target end
  438. if a_execute_target.project /= Current then
  439. a_execute_target.project.execute_target (a_execute_target, a_arguments, a_force, a_polymorph)
  440. else
  441. target_arguments_stack.force (a_arguments)
  442. a_execute_target.execute
  443. target_arguments_stack.remove
  444. end
  445. target_locals_stack.remove
  446. targets_stack.remove
  447. end
  448. check current_target = old_current_target end
  449. end
  450. feature -- Output
  451. trace (a_message: ARRAY [STRING])
  452. -- Write `a_message' to standard output unless `verbose' = False.
  453. require
  454. a_message_not_void: a_message /= Void
  455. -- Note: ARRAY.has is not portable:
  456. -- no_void_message: not a_message.has (Void)
  457. local
  458. i, nb: INTEGER
  459. do
  460. if options.verbose then
  461. i := a_message.lower
  462. nb := a_message.upper
  463. from until i > nb loop
  464. output_file.put_string (a_message.item (i))
  465. i := i + 1
  466. end
  467. output_file.put_new_line
  468. output_file.flush
  469. end
  470. end
  471. log (a_message: ARRAY [STRING])
  472. -- Write `a_message' to standard output.
  473. require
  474. a_message_not_void: a_message /= Void
  475. -- Note: ARRAY.has is not portable:
  476. -- no_void_message: not a_message.has (Void)
  477. local
  478. i, nb: INTEGER
  479. do
  480. i := a_message.lower
  481. nb := a_message.upper
  482. from until i > nb loop
  483. output_file.put_string (a_message.item (i))
  484. i := i + 1
  485. end
  486. output_file.put_new_line
  487. output_file.flush
  488. end
  489. trace_debug (a_message: ARRAY [STRING])
  490. -- Write `a_message' to standard output unless `debug_mode' = False.
  491. require
  492. a_message_not_void: a_message /= Void
  493. -- Note: ARRAY.has is not portable:
  494. -- no_void_message: not a_message.has (Void)
  495. local
  496. i, nb: INTEGER
  497. do
  498. if options.debug_mode then
  499. i := a_message.lower
  500. nb := a_message.upper
  501. from until i > nb loop
  502. output_file.put_string (a_message.item (i))
  503. i := i + 1
  504. end
  505. output_file.put_new_line
  506. output_file.flush
  507. end
  508. end
  509. output_file: KI_TEXT_OUTPUT_STREAM
  510. -- Output file
  511. set_output_file (a_file: like output_file)
  512. -- Set `output_file' to `a_file'.
  513. require
  514. a_file_not_void: a_file /= Void
  515. a_file_open_write: a_file.is_open_write
  516. do
  517. output_file := a_file
  518. ensure
  519. output_file_set: output_file = a_file
  520. end
  521. feature {GEANT_COMMAND} -- Change variable
  522. set_variable_value (a_name, a_value: STRING_8)
  523. -- Set value of variable `a_name' to `a_value'.
  524. -- Either local or global depending the case.
  525. require
  526. a_name_not_void: a_name /= Void
  527. a_name_not_empty: a_name.count > 0
  528. a_value_not_void: a_value /= Void
  529. local
  530. vars: GEANT_VARIABLES
  531. do
  532. if is_local_variable (a_name) then
  533. vars := target_locals_stack.item
  534. else
  535. vars := variables
  536. end
  537. vars.set_variable_value (a_name, a_value)
  538. end
  539. unset_variable (a_name: STRING_8)
  540. -- Unset variable `a_name'
  541. -- Either local or global depending the case.
  542. require
  543. a_name_not_void: a_name /= Void
  544. a_name_not_empty: a_name.count > 0
  545. local
  546. vars: GEANT_VARIABLES
  547. do
  548. if is_local_variable (a_name) then
  549. vars := target_locals_stack.item
  550. if vars.has (a_name) then
  551. vars.replace (create {STRING}.make_empty, a_name)
  552. end
  553. else
  554. variables.remove (a_name)
  555. end
  556. end
  557. is_local_variable (a_name: STRING): BOOLEAN
  558. -- Is variable `a_name' local ?
  559. require
  560. a_name_not_void: a_name /= Void
  561. a_name_not_empty: a_name.count > 0
  562. do
  563. if not attached current_target as l_current_target then
  564. Result := options.variable_local_by_default
  565. elseif l_current_target.formal_locals.has (a_name) then
  566. Result := True
  567. elseif l_current_target.formal_globals.has (a_name) then
  568. Result := False
  569. else
  570. Result := options.variable_local_by_default
  571. end
  572. end
  573. feature {GEANT_COMMAND} -- Access GEANT_COMMAND
  574. targets_stack: DS_STACK [GEANT_TARGET]
  575. -- Stack of targets
  576. current_target: detachable GEANT_TARGET
  577. -- Currently executing target;
  578. -- Set during processing `execute_target'
  579. do
  580. if not targets_stack.is_empty then
  581. Result := targets_stack.item
  582. end
  583. end
  584. invariant
  585. name_not_void: name /= Void
  586. name_not_empty: not name.is_empty
  587. no_void_target: attached targets as l_targets implies not l_targets.has_void
  588. output_file_not_void: output_file /= Void
  589. output_file_open_write: output_file.is_open_write
  590. variables_not_void: variables /= Void
  591. end