/[eiffelstudio]/branches/eth/eve/Src/library/memory_analyzer/ma_object_snapshot_mediator.e
ViewVC logotype

Contents of /branches/eth/eve/Src/library/memory_analyzer/ma_object_snapshot_mediator.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 92408 - (show annotations)
Fri Apr 5 09:22:00 2013 UTC (6 years, 9 months ago) by jasonw
File size: 21782 byte(s)
<<Merged from trunk#92407.>>
1 note
2 description: "Objects that show the whole system's memory objects in a grid."
3 legal: "See notice at end of class."
4 status: "See notice at end of class."
5 date: "$Date$"
6 revision: "$Revision$"
7
8 class
9 MA_OBJECT_SNAPSHOT_MEDIATOR
10
11 inherit
12 MA_SINGLETON_FACTORY
13
14 create
15 make_with_grid
16
17 feature -- Initlization
18
19 make_with_grid (a_grid: EV_GRID)
20 -- Creation method
21 require
22 a_grid_not_void: a_grid /= Void
23 do
24 object_grid := a_grid
25
26 object_grid.enable_single_row_selection
27 object_grid.enable_tree
28 object_grid.enable_partial_dynamic_content
29 object_grid.insert_new_column (1)
30 object_grid.insert_new_column (2)
31 object_grid.insert_new_column (3)
32 object_grid.column (1).set_title ("Object type")
33 object_grid.column (2).set_title ("Count/Address")
34 object_grid.column (3).set_title ("Delta/Start Object")
35 object_grid.column (1).header_item.pointer_button_press_actions.force_extend (agent on_grid_header_click (1))
36 object_grid.column (2).header_item.pointer_button_press_actions.force_extend (agent on_grid_header_click (2))
37 object_grid.column (3).header_item.pointer_button_press_actions.force_extend (agent on_grid_header_click (3))
38
39 object_grid.column (1).header_item.pointer_double_press_actions.force_extend (agent adjust_column_width (1))
40 object_grid.column (2).header_item.pointer_double_press_actions.force_extend (agent adjust_column_width (2))
41 object_grid.column (3).header_item.pointer_double_press_actions.force_extend (agent adjust_column_width (3))
42
43 object_grid.set_pick_and_drop_mode
44 object_grid.set_item_pebble_function (agent pick_item)
45
46 object_grid.column (1).set_width (500)
47 object_grid.column (2).set_width (100)
48 object_grid.column (3).set_width (100)
49
50 -- object_grid.set_item_pebble_function (agent pick_item_for_filter)
51 show_memory_map
52 ensure
53 object_grid_column_added: object_grid.column_count = 3
54 object_grid_accept_cursor_set: object_grid.accept_cursor /= Void
55 object_grid_deny_curosor_set: object_grid.deny_cursor /= Void
56 end
57
58 adjust_column_width (a_column_index: INTEGER)
59 -- adjust a column width to fix the max width of the item its contain
60 require
61 a_column_index_valid: column_index_valid (a_column_index)
62 do
63 if object_grid.row_count > 0 then
64 object_grid.column (a_column_index).set_width (object_grid.column (a_column_index).required_width_of_item_span (1, object_grid.row_count))
65 end
66 end
67
68 feature -- Command
69
70 show_memory_map
71 -- Show memory map
72 local
73 l_new_table: HASH_TABLE [INTEGER, INTEGER]
74 l_old_table: detachable HASH_TABLE [INTEGER, INTEGER]
75 i: INTEGER
76 l_int: INTERNAL
77 l_name: STRING
78 l_count, l_delta: INTEGER
79 l_data: like grid_data
80 l_map: detachable HASH_TABLE [ARRAYED_LIST [ANY], INTEGER_32]
81 do
82 -- Reduce as much as possible relations.
83 name_table := Void
84 reference_table := Void
85 selected_item := Void
86 grid_data := Void
87 once_object_table := Void
88 selected_index := 0
89 grid_util.grid_remove_and_clear_all_rows (object_grid)
90
91 -- Get the data right away.
92 system_util.collect
93 l_new_table := memory.memory_count_map
94
95 -- Process `l_new_table' and fill `output_grid' with associated data.
96 from
97 create l_int
98 l_new_table.start
99 l_old_table := last_table
100 create l_data.make (l_new_table.count)
101 if finding_route_to_once then
102 create name_table.make (l_new_table.count * 40)
103 create reference_table.make (l_new_table.count * 100)
104 create object_table.make (1000)
105 build_once_object_table
106 l_map := memory.memory_map
107 memory.collection_off
108 end
109 i := 1
110 until
111 l_new_table.after
112 loop
113 l_name := l_int.type_name_of_type (l_new_table.key_for_iteration)
114
115 l_count := l_new_table.item_for_iteration
116
117 if finding_route_to_once then
118 check attached l_map end -- Implied by `finding_route_to_once'
119 add_to_reference_table (l_new_table.key_for_iteration, l_map)
120 end
121
122 -- Compute `l_delta' now.
123 if l_old_table /= Void then
124 l_old_table.search (l_new_table.key_for_iteration)
125 if l_old_table.found then
126 l_delta := l_new_table.item_for_iteration - l_old_table.found_item
127 l_old_table.remove (l_new_table.key_for_iteration)
128 else
129 l_delta := l_new_table.item_for_iteration
130 end
131 else
132 l_delta := l_new_table.item_for_iteration
133 end
134 l_data.extend ([l_name, l_count, l_delta, l_new_table.key_for_iteration])
135 i := i + 1
136 l_new_table.forth
137 end
138
139 if l_old_table /= Void and then not l_old_table.is_empty then
140 from
141 l_old_table.start
142 until
143 l_old_table.after
144 loop
145 l_name := l_int.type_name_of_type (l_old_table.key_for_iteration)
146 l_count := 0
147 l_delta := - l_old_table.item_for_iteration
148 l_data.extend ([l_name, l_count, l_delta, l_old_table.key_for_iteration])
149 i := i + 1
150 l_old_table.forth
151 end
152 end
153
154 if finding_route_to_once then
155 memory.collection_on
156 last_selected_object := Void
157 end
158
159 last_table := l_new_table
160 grid_data := l_data
161
162 update_grid_content
163 end
164
165 set_finding_route_to_once (a_b: BOOLEAN)
166 -- Set `finding_route_to_once' with `b'.
167 do
168 finding_route_to_once := a_b
169 end
170
171 feature {NONE} -- Implementation
172
173 pick_item (a_item: EV_GRID_ITEM): MA_STONE
174 -- User pick one item from the grid.
175 require
176 set: attached a_item
177 valid: a_item.column.index = 1
178 do
179 if a_item /= Void and then a_item.column.index = 1 then
180 -- If is an item represent a object. Only an item represent an object has been setted the data.
181 if attached a_item.data as l_data then
182 create {MA_OBJECT_STONE} Result.make (l_data)
183 object_grid.set_accept_cursor (accept_node)
184 object_grid.set_deny_cursor (deny_node)
185 else
186 -- If is an item represent a class.
187 if attached {EV_GRID_LABEL_ITEM} a_item as l_item then
188 create {MA_CLASS_STONE} Result.make (l_item.text)
189 else
190 create {MA_CLASS_STONE} Result.make ("Unknown grid item")
191 end
192 object_grid.set_accept_cursor (accept_node_class)
193 object_grid.set_deny_cursor (deny_node_class)
194 end
195 else
196 check False end -- Implied by precondition
197 create {MA_CLASS_STONE} Result.make ("") -- Satisfy void-safe compiler
198 end
199 end
200
201 on_grid_header_click (a_column_index: INTEGER)
202 -- User click on the column header of index `a_column_index'.
203 require
204 a_column_index_valid: column_index_valid (a_column_index)
205 output_grid_not_destroyed: not object_grid.is_destroyed
206 do
207 if object_grid.header.pointed_divider_index = 0 then
208 if sorted_column = a_column_index then
209 -- We invert the sorting.
210 sorting_order := not sorting_order
211 else
212 sorted_column := a_column_index
213 sorting_order := False
214 end
215 if grid_data /= Void then
216 sort_data
217 update_grid_content
218 end
219 end
220 end
221
222 sort_data
223 -- Sort `grid_data' according to `sorted_column' and `sorting_order'.
224 require
225 grid_data_not_void: grid_data /= Void
226 local
227 l_sorter: QUICK_SORTER [like row_data]
228 l_agent_sorter: AGENT_EQUALITY_TESTER [like row_data]
229 l_grid_data: like grid_data
230 do
231 inspect
232 sorted_column
233 when 1 then create l_agent_sorter.make (agent sort_on_type_name)
234 when 2 then create l_agent_sorter.make (agent sort_on_count)
235 when 3 then create l_agent_sorter.make (agent sort_on_delta)
236 end
237 create l_sorter.make (l_agent_sorter)
238 l_grid_data := grid_data
239 check attached l_grid_data end -- Implied by precondition
240 l_sorter.sort (l_grid_data)
241 end
242
243 update_grid_content
244 -- Fill grid using `grid_data'
245 require
246 grid_data_not_void: grid_data /= Void
247 local
248 l_data: like grid_data
249 l_row_data: like row_data
250 l_item: MA_GRID_LABEL_ITEM
251 i, l_count, l_delta: INTEGER
252 l_str: STRING
253 l_row: EV_GRID_ROW
254 l_grid: like object_grid
255 do
256 from
257 l_data := grid_data
258 l_grid := object_grid
259 grid_util.grid_remove_and_clear_all_rows (l_grid)
260 i := 1
261 check attached l_data end -- Implied by precondition `grid_data_not_void'
262 l_data.start
263 until
264 l_data.after
265 loop
266 l_row_data := l_data.item_for_iteration
267 if not filter.filter_class (l_row_data.type_name) then
268 l_str := l_row_data.type_name
269 check
270 l_str_not_void: l_str /= Void
271 end
272
273 -- Set type name
274 create l_item.make_with_text (l_str)
275 l_item.set_pixmap (icons.object_grid_class_icon)
276 l_grid.set_item (1, i, l_item)
277
278 -- Set count
279 l_count := l_row_data.number_of_objects
280 create l_item.make_with_text (l_count.out)
281 l_grid.set_item (2, i, l_item)
282 if l_count >= 1 then
283 l_row := l_grid.row (i)
284 l_row.ensure_expandable
285 l_row.expand_actions.extend (agent on_expand_actions_for_type (l_row_data.type_id, l_row))
286 end
287
288 -- Set delta
289 l_delta := l_row_data.variation_since_last_time
290 if l_delta /= 0 then
291 create l_item.make_with_text (l_delta.out)
292 if l_delta > 0 then
293 l_item.set_foreground_color (increased_color)
294 else
295 l_item.set_foreground_color (decreased_color)
296 end
297 l_grid.set_item (3, i, l_item)
298 end
299 i := i + 1
300 end
301 l_data.forth
302 end
303 -- We launch a collection, so that no bad information is displayed
304 -- for referers.
305 system_util.collect
306 end
307
308 on_expand_actions_for_type (a_dynamic_type: INTEGER; a_parent_row: EV_GRID_ROW)
309 -- Add all objects of the given dynamic type of `a_dynamic_type' as subnode
310 -- of row `a_parent_row'.
311 require
312 output_grid_not_destroyed: not object_grid.is_destroyed
313 a_dynamic_type_non_negative: a_dynamic_type >= 0
314 a_parent_row_not_void: a_parent_row /= Void
315 local
316 l_data: SPECIAL [ANY]
317 l_item: MA_GRID_LABEL_ITEM
318 l_check_item: MA_GRID_CHECK_BOX_ITEM
319 l_row_index, i, j, nb: INTEGER
320 l_row: EV_GRID_ROW
321 l_any: ANY
322 do
323 if a_parent_row.subrow_count = 0 then
324
325 l_data := memory.objects_instance_of_type (a_dynamic_type)
326 if l_data /= Void then
327
328 debug ("larry")
329 io.put_string ("%Nin MA_OBJECT_SNAPSHOT_MEDIATOR: void object? " + l_data.count.out + " orignal object is: " + internal.type_name_of_type (a_dynamic_type))
330 end
331 --| FIXIT: Why get void object here? There sometime a void object...?
332 object_grid.insert_new_rows_parented (l_data.count, a_parent_row.index + 1, a_parent_row)
333 from
334 i := 0
335 nb := l_data.count
336 l_row_index := a_parent_row.index
337 j := l_row_index + 1
338 until
339 i = nb
340 loop
341 l_any := l_data.item (i)
342 i := i + 1
343 if l_any /= Void then
344 create l_item.make_with_text ((j - l_row_index).out)
345 l_item.set_pixmap (icons.object_grid_icon)
346 object_grid.set_item (1, j, l_item)
347 l_item.set_data (l_any)
348 create l_item.make_with_text (($l_any).out)
349 l_item.set_data (l_any)
350 object_grid.set_item (2, j, l_item)
351
352 create l_check_item.make_with_boolean (False)
353 l_check_item.selected_changed_actions.extend (agent on_check_box_selected (?, l_any))
354 object_grid.set_item (3, j, l_check_item)
355
356 l_row := object_grid.row (j)
357 l_row.ensure_expandable
358 l_row.expand_actions.extend (agent on_expand_actions_for_referers (l_any, l_row))
359 j := j + 1
360 end
361 end
362 end
363 end
364 end
365
366 on_expand_actions_for_referers (an_object: ANY; a_parent_row: EV_GRID_ROW)
367 -- Add all objects referring to `an_object' as subnode
368 -- of row `a_parent_row'.
369 require
370 output_grid_not_destroyed: not object_grid.is_destroyed
371 an_object_not_void: an_object /= Void
372 a_parent_row_not_void: a_parent_row /= Void
373 local
374 l_data: SPECIAL [ANY]
375 l_item: MA_GRID_LABEL_ITEM
376 l_check_item: MA_GRID_CHECK_BOX_ITEM
377 l_row_index: INTEGER
378 i, j, nb: INTEGER
379 l_int: INTERNAL
380 l_any: ANY
381 l_row: EV_GRID_ROW
382 l_string: STRING
383 l_count: INTEGER
384 do
385 if a_parent_row.subrow_count = 0 then
386 l_data := memory.referers (an_object)
387 if l_data /= Void then
388 create l_int
389 from
390 j := 0
391 nb := l_data.count
392 until
393 j = nb
394 loop
395 l_string := l_int.type_name (l_data.item (j))
396 if not is_object_from_ma (l_string) then
397 l_count := l_count + 1
398 end
399 j := j + 1
400 end
401 from
402 l_row_index := a_parent_row.index
403 i := l_row_index + 1
404 j := 0
405 nb := l_data.count
406 object_grid.insert_new_rows_parented (l_count, i, a_parent_row)
407 until
408 j = nb
409 loop
410 l_string := l_int.type_name (l_data.item (j))
411 if not is_object_from_ma (l_string) then
412 create l_item.make_with_text ((i - l_row_index).out + ": " + l_string)
413 l_item.set_data (l_data.item (j))
414 l_item.set_pixmap (icons.object_grid_icon)
415 object_grid.set_item (1, i, l_item)
416 l_any := l_data.item (j)
417 create l_item.make_with_text (($l_any).out)
418 l_item.set_data (l_data.item (j))
419 object_grid.set_item (2, i, l_item)
420 create l_check_item.make_with_boolean (False)
421 l_check_item.selected_changed_actions.extend (agent on_check_box_selected (?, l_any))
422 object_grid.set_item (3, i, l_check_item)
423 l_row := object_grid.row (i)
424 l_row.ensure_expandable
425 l_row.expand_actions.extend (agent on_expand_actions_for_referers (l_data.item (j), l_row))
426 i := i + 1
427 end
428 j := j + 1
429 end
430 end
431 end
432 end
433
434 on_check_box_selected (a_check_item: MA_GRID_CHECK_BOX_ITEM; a_object: ANY)
435 -- On check box selected.
436 require
437 a_check_item_not_void: a_check_item /= Void
438 do
439 if a_check_item.selected then
440 last_selected_object := a_object
441 if attached selected_item as l_item then
442 l_item.set_selected (False)
443 end
444 selected_item := a_check_item
445 end
446 end
447
448 add_to_reference_table (a_object_id: INTEGER; a_map: HASH_TABLE [ARRAYED_LIST [ANY], INTEGER_32])
449 -- Added all referer relations of objects of `a_object_id'.
450 require
451 tables_created: reference_table /= Void and name_table /= Void
452 a_map_not_void: a_map /= Void
453 has: a_map.has (a_object_id)
454 set: attached object_table
455 set: attached name_table
456 set: attached reference_table
457 local
458 l_name, l_field_name: STRING
459 l_int: INTERNAL
460 l_objects_of_type: detachable ARRAYED_LIST [ANY]
461 l_index: NATURAL
462 l_item: ANY
463 l_referee: detachable ANY
464 l_field_count: INTEGER
465 i: INTEGER
466 l_object_table: like object_table
467 l_name_table: like name_table
468 l_reference_table: like reference_table
469 do
470 create l_int
471 l_name := l_int.type_name_of_type (a_object_id)
472 l_objects_of_type := a_map.item (a_object_id)
473 check attached l_objects_of_type end -- Implied by precondition `has'
474 l_object_table := object_table
475 check attached l_object_table end -- Implied by precondition `set'
476 l_reference_table := reference_table
477 check attached l_reference_table end -- Implied by precondition `set'
478
479 from
480 l_objects_of_type.start
481 until
482 l_objects_of_type.after
483 loop
484 l_item := l_objects_of_type.item
485 l_index := l_object_table.index (l_item)
486 if last_selected_object /= Void and then l_item = last_selected_object then
487 selected_index := l_index
488 last_selected_object := Void
489 end
490 --| Fixme: we don't know whether it is an once object or not.
491 l_name_table := name_table
492 check attached l_name_table end -- Implied by precondition `set'
493 l_name_table.put (l_name, l_index)
494 check
495 not l_name_table.conflict
496 end
497 if attached {SPECIAL [detachable ANY]} l_item as l_special then
498 l_field_name := once "(special_field)"
499 from
500 i := l_special.lower
501 until
502 i > l_special.upper
503 loop
504 l_referee := l_special.item (i)
505 if l_referee /= Void then
506 l_reference_table.extend (l_index, l_object_table.index (l_referee), l_field_name)
507 end
508 i := i + 1
509 end
510 elseif attached {TUPLE} l_item as l_tuple then
511 l_field_name := once "(tuple_field)"
512 from
513 i := l_tuple.lower
514 until
515 i > l_tuple.upper
516 loop
517 l_referee := l_tuple.item (i)
518 if l_referee /= Void then
519 l_reference_table.extend (l_index, l_object_table.index (l_referee), l_field_name)
520 end
521 i := i + 1
522 end
523 else
524 from
525 l_field_count := l_int.field_count_of_type (a_object_id)
526 i := 1
527 until
528 i > l_field_count or l_item = Current
529 loop
530 l_referee := l_int.field (i, l_item)
531 if l_referee /= Void then
532 l_field_name := l_int.field_name (i, l_item)
533 l_reference_table.extend (l_index, l_object_table.index (l_referee), l_field_name)
534 end
535 i := i + 1
536 end
537 end
538 l_objects_of_type.forth
539 end
540 end
541
542 build_once_object_table
543 -- Record once object in `once_object_table'.
544 require
545 set: attached object_table
546 local
547 l_obj: like once_objects
548 i: INTEGER
549 l_item: ANY
550 l_index: like selected_index
551 l_int: INTERNAL
552 l_once_object_table: like once_object_table
553 l_object_table: like object_table
554 do
555 create l_int
556 create l_once_object_table.make (100)
557 once_object_table := l_once_object_table
558 l_obj := once_objects
559 from
560 i := l_obj.lower
561 until
562 i > l_obj.upper
563 loop
564 l_item := l_obj.item (i)
565 if l_item /= Void then
566 l_object_table := object_table
567 check attached l_object_table end -- Implied by precondition `set'
568 l_index := l_object_table.index (l_item)
569 l_once_object_table.force (l_index, l_index)
570 end
571 i := i + 1
572 end
573 end
574
575 feature -- Status report
576
577 is_object_from_ma (a_str: STRING): BOOLEAN
578 -- If the type of object is from MA.
579 do
580 if a_str /= Void then
581 Result := a_str.is_equal (once "MA_GRID_LABEL_ITEM") or else
582 a_str.is_equal (once "TUPLE [MA_OBJECT_SNAPSHOT_MEDIATOR, ANY, EV_GRID_ROW]") or else
583 --a_str.is_equal (once "MA_OBJECT_SNAPSHOT_MEDIATOR") or else
584 a_str.is_equal (once "TUPLE [MA_OBJECT_SNAPSHOT_MEDIATOR, ANY]") or else
585 a_str.has_substring ("MA_OBJECT_SNAPSHOT")
586 end
587 end
588
589 column_index_valid (a_column_index: INTEGER): BOOLEAN
590 -- Validate a column index.
591 do
592 Result := a_column_index > 0 and a_column_index <= object_grid.column_count
593 end
594
595 finding_route_to_once: BOOLEAN
596
597 feature {NONE} -- Fields
598
599 row_data: TUPLE [type_name: STRING; number_of_objects: INTEGER; variation_since_last_time: INTEGER; type_id: INTEGER]
600 -- Type for the data inserted in `output_grid'
601 -- It is [type_name, number_of_objects, variation_since_last_time, type_id].
602 local
603 l_result: detachable like row_data
604 do
605 check False end -- Anchor type only
606 check attached l_result end -- Satisfy void-safe compiler
607 Result := l_result
608 end
609
610 object_grid: EV_GRID
611 -- the main grid to show object snapshot datas
612
613 sorted_column: INTEGER
614 -- Column on which sorting is done.
615
616 sorting_order: BOOLEAN
617 -- If True, sorted from the smaller to the bigger.
618
619 last_table: detachable HASH_TABLE [INTEGER, INTEGER]
620 -- Result of last call to `mem.memory_map_count' in `show_memory_map'.
621
622 grid_data: detachable ARRAYED_LIST [like row_data]
623 -- Data used to fill grid.
624
625 feature -- Access
626
627 reference_table: detachable MA_REFERENCES_TABLE [like selected_index, like selected_index]
628 -- Reference addresses mapping at a certain time. [referrer index, referee index]
629
630 object_table: detachable SED_OBJECTS_TABLE
631 -- Table to store all indice of objects.
632
633 once_object_table: detachable HASH_TABLE [like selected_index, like selected_index]
634 -- Table to store all once objects.
635
636 name_table: detachable HASH_TABLE [STRING, like selected_index]
637 -- Names of objects of addresses at a certain time. [Name, index]
638
639 selected_index: NATURAL
640 -- Index of `last_selected_object' at a time.
641
642 feature {NONE} -- Route building.
643
644 last_selected_object: detachable ANY
645 -- A selected object.
646
647 selected_item: detachable MA_GRID_CHECK_BOX_ITEM
648 -- All selected items.
649
650 feature {NONE} -- Sorting Implemention
651
652 sort_on_type_name (u, v: like row_data): BOOLEAN
653 -- Compare u, v.
654 require
655 u_not_void: u /= Void
656 v_not_void: v /= Void
657 local
658 l_string1, l_string2: STRING
659 do
660 l_string1 := u.type_name
661 l_string2 := v.type_name
662 check
663 l_string1_not_void: l_string1 /= Void
664 l_string2_not_void: l_string2 /= Void
665 end
666 if sorting_order then
667 Result := l_string1 < l_string2
668 else
669 Result := l_string2 < l_string1
670 end
671 end
672
673 sort_on_count (u, v: like row_data): BOOLEAN
674 -- Compare u, v.
675 require
676 u_not_void: u /= Void
677 v_not_void: v /= Void
678 do
679 if sorting_order then
680 Result := u.number_of_objects < v.number_of_objects
681 else
682 Result := v.number_of_objects < u.number_of_objects
683 end
684 end
685
686 sort_on_delta (u, v: like row_data): BOOLEAN
687 -- Compare u, v.
688 require
689 u_not_void: u /= Void
690 v_not_void: v /= Void
691 do
692 if sorting_order then
693 Result := u.variation_since_last_time < v.variation_since_last_time
694 else
695 Result := v.variation_since_last_time < u.variation_since_last_time
696 end
697 end
698
699 feature {NONE} -- Internal
700
701 once_objects: SPECIAL [ANY]
702 do
703 Result := {ISE_RUNTIME}.once_objects (special_any_dynamic_type)
704 end
705
706 special_any_dynamic_type: INTEGER
707 -- Dynamic type ID of an instance of `SPECIAL [ANY]'
708 local
709 a: ARRAY [ANY]
710 spec: SPECIAL [ANY]
711 l_inte: INTERNAL
712 once
713 create a.make (0, 0)
714 spec := a.area
715 create l_inte
716 Result := l_inte.dynamic_type (spec)
717 end
718
719 invariant
720 object_grid_not_void: object_grid /= Void
721
722 note
723 copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
724 license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
725 source: "[
726 Eiffel Software
727 5949 Hollister Ave., Goleta, CA 93117 USA
728 Telephone 805-685-1006, Fax 805-685-6869
729 Website http://www.eiffel.com
730 Customer support http://support.eiffel.com
731 ]"
732
733
734
735
736 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23