source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/util/oasisgui/opentea/dTree.tcl @ 4775

Last change on this file since 4775 was 4775, checked in by aclsce, 5 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 24.1 KB
Line 
1#  This program is under CECILL_B licence. See footer for details.
2
3# This library is intended to provide a new data structure, the tree, to Tcl 8.5 using dictionaries
4
5#####################
6# Adresses procedures
7#####################
8
9proc gui2tree address {
10    return [split $address .]
11}
12
13proc tree2gui address {
14    return [join $address .]
15}
16
17proc addrGetFather address {
18    return [tree2gui [lrange [gui2tree $address] 0 end-1]]
19}
20
21proc addrGetAncestors address {
22    set result ""
23    while {$address != ""} {
24        set address [addrGetFather $address]
25        if {$address != ""} {
26            lappend result $address
27        }
28    }
29    return $result
30}
31
32# This procedure creates a tree by creating the root node
33proc dTree_init {dtree} {
34    upvar $dtree tree
35    set tree [dict create]
36    dict set tree "root" description "root of the tree"
37    dict set tree "root" nodeType "node"
38    dict set tree "root" children [list]
39}
40
41
42# This procedure adds a node named node as a children of key in the tree dtree
43proc dTree_addNode {dtree key node} {
44     upvar $dtree tree
45   
46     if {[dict exists $tree $key]} {
47             
48        if {[dict exists $tree "$key $node"]} {
49            error "The node you are trying to add already exists ($key $node)"
50        }
51        set value [dict get $tree $key children]
52        lappend value $node
53        dict set tree $key children $value
54        lappend key $node
55        dict set tree $key children ""
56     } else {
57        #If the father doesn't exist, let's create it !
58        dTree_addNode tree [lrange $key 0 end-1] [lindex $key end]
59        dTree_addNode tree $key $node
60        dTree_setAttribute tree "$key" "value" ""
61        #error "You're trying to add a node but the father node ($key) doesn't exist"
62     }
63}
64
65# used to deref multiple nodes
66proc dTree_cleanKey2 { key } {
67    set key2 ""
68    foreach key_elt $key {
69        if {[string match item_* $key_elt]} {
70            lappend key2 "item"
71        } else {
72            lappend key2 $key_elt
73        }
74    }
75    return $key2
76}
77
78#  fonctionne , mais delicat a cause de l'addresse qui doit etre protégée par des {}
79proc dTree_cleanKey { key } {
80    foreach j [lsearch -all  $key "item_*"] {
81        set key [ lset key $j "item"]
82    }
83    return $key
84}
85
86proc dTree_setAttribute {dtree key attribute value} {
87    upvar $dtree tree
88    if {[dict exists $tree $key]} {
89        dict set tree $key $attribute $value 
90    } else {
91        #error "You're trying to set an attribute on a node which doesn't exist"
92        dTree_addNode tree [lrange $key 0 end-1] [lindex $key end]
93        dict set tree $key $attribute $value       
94    }
95}
96
97
98
99proc dTree_getAttribute_fast {tree key attribute} {
100    return [dict get $tree "$key" $attribute]
101}
102
103
104proc dTree_getAttribute {tree key attribute} {
105   
106    if {[dict exists $tree "$key" $attribute]} {
107        return [dict get $tree "$key" $attribute]
108    } else {
109        set key_clean [dTree_cleanKey $key]
110        if {[dict exists $tree $key_clean $attribute]} {
111            return [dict get $tree $key_clean $attribute]
112        } else {
113            error "You're trying to get an attribute which doesn't exist : $key > $attribute"
114        }
115    }
116   
117}
118
119
120proc dTree_tryGetAttribute_fast {tree key attribute default} {
121   
122    if {[dict exists $tree "$key" $attribute]} {
123        return [dict get $tree "$key" $attribute]
124    } else {   
125        return $default
126    } 
127}
128
129
130proc dTree_tryGetAttribute {tree key attribute default} {
131   
132    if {[dict exists $tree "$key" $attribute]} {
133        return [dict get $tree "$key" $attribute]
134    } else {
135        set key_clean [dTree_cleanKey $key]
136        if {[dict exists $tree $key_clean  $attribute]} {
137            return [dict get $tree $key_clean  $attribute]
138        } else {
139            return $default
140        }
141    } 
142}
143
144
145
146proc dTree_getAttributes {tree node} {
147    set result ""
148    dict for {key value} [dict get "$tree" "$node"] {
149        if {$key != "children"} {lappend result [list $key $value]}
150    }
151    return $result
152}
153
154
155proc dTree_getChildren_fast {tree key} {
156    return [dict get $tree "$key" "children"]
157}
158
159proc dTree_getChildren {tree key} {
160    #return [dict get $tree $key "children"]
161    if {[dict exists $tree "$key" "children"]} {
162        return [dict get $tree "$key" "children"]
163    } else {
164        set key_clean [dTree_cleanKey $key]
165        if {[dict exists $tree $key_clean "children"]} {
166            return [dict get $tree $key_clean "children"]
167        } else {
168            error "You're trying to get children from a node which doesn't exist : $key "
169        }
170    }
171}
172
173proc dTree_getUsedChildren {tree key} {
174    # This function acts like dTree_getChildren but it returns relevant children only
175    # For example, in a xor, only the selected children are returned
176    # This procedure should only be used in tmpTree
177    global XMLtree widgetInfo
178    set cleanKey [dTree_cleanKey $key]
179    if {[dTree_attrExists $XMLtree $cleanKey "nodeType"]} {
180        set nodeType [dTree_getAttribute_fast $XMLtree $cleanKey "nodeType"]
181        switch $nodeType {
182            "xor" {
183                return [dTree_getAttribute_fast $tree $key "value"]
184            }
185            default {
186                set finalChildren ""
187                set children [dTree_getChildren $tree $key]
188                foreach child $children {
189                    if {[info exists widgetInfo([tree2gui "$key $child"]-visible)] == 0} {
190                        lappend finalChildren $child                       
191                    } elseif {$widgetInfo([tree2gui "$key $child"]-visible) == 1} {               
192                        lappend finalChildren $child
193                    }
194                }
195                return $finalChildren
196            }
197        }
198    } else {
199        #warning "The node $key doesn't have a corresponding node in the XMLtree"
200        #eturn [dTree_getChildren $tree $key]
201        return ""
202    }
203 
204}
205
206proc dTree_rmAttribute {dtree key attribute} {
207    upvar $dtree tree
208    if {[dict exists $tree $key $attribute]} {
209        dict unset tree $key $attribute 
210    } else {
211        error 0 "You're trying to remove an attribute which doesn't exist"
212    }
213}
214
215proc dTree_rmNode {dtree key} {
216    upvar $dtree tree
217    if {[dict exists $tree $key]} {
218        dict unset tree $key
219        set father [lrange $key 0 end-1]
220        set child [lrange $key end end]
221        set fatherListChildren [dict get $tree $father children]
222        set idx [lsearch -exact $fatherListChildren $child]
223        set fatherListChildren [lreplace $fatherListChildren $idx $idx]
224        dict set tree $father children $fatherListChildren
225    } else {
226        error "You're trying to remove a node which doesn't exist"
227    }
228   
229}
230
231proc dTree_rmBranch {dtree node} {
232    upvar $dtree tree
233    foreach child [dTree_getChildren $tree "$node"] {
234        dTree_rmBranch tree "$node $child"
235    }
236    dTree_rmNode tree "$node"
237}
238
239# behaves like a cp
240# node source adress like : aze rty uio node1
241# node destination addres like : qsd fgh jkl
242# output is : qsd fgh jkl node1
243
244# "nodeName" is the future father of the copied node
245# $node_dest $nodeName" is the full address of the copied node
246
247
248proc dTree_copyBranch {dtree_source node_source dtree_dest node_dest} {
249    upvar $dtree_source tree1
250    upvar $dtree_dest tree2
251    set nodeName [lindex $node_source end]
252   
253    if {[dTree_nodeExists $tree1 "$node_source"]==0} {
254        warning "Cannot copy branch $nodeName from $dtree_source "
255        return 
256    }
257   
258   
259   
260    if {[dTree_nodeExists $tree2 "$node_dest $nodeName"]} {
261        dTree_rmBranch tree2 "$node_dest $nodeName"
262    }
263    dTree_addNode tree2 "$node_dest" $nodeName
264   
265    foreach attribute [dTree_getAttributes $tree1 $node_source] {
266        dTree_setAttribute tree2 "$node_dest $nodeName" [lindex $attribute 0] [lindex $attribute 1]
267    }
268   
269    foreach child [dTree_getChildren $tree1 $node_source] {
270        dTree_copyBranch tree1 "$node_source $child" tree2 "$node_dest $nodeName"
271    }
272}
273
274# to give to a node the same children as an other node
275proc dTree_duplicateBranch {dtree_source node_source node_dest} {
276    upvar $dtree_source tree
277   
278    set sce_path  [lrange $node_source 0 end-1 ]
279    set sce_node  [lindex $node_source end ]
280    set tgt_path  [lrange $node_dest 0 end-1 ]
281    set tgt_node  [lindex $node_dest end ]
282   
283   
284    set value [dTree_getAttribute $tree $node_dest "value" ]
285             
286    dTree_rmBranch tree "$tgt_path $tgt_node"
287    dTree_addNode tree "$tgt_path"  $tgt_node
288   
289   
290    foreach attribute [dTree_getAttributes $tree $node_source] {
291        dTree_setAttribute tree $node_dest [lindex $attribute 0] [lindex $attribute 1]
292    }
293    dTree_setAttribute tree $node_dest "value" $value   
294   
295   
296    foreach child [dTree_getChildren $tree $node_source] {
297        dTree_copyBranch tree "$node_source $child" tree "$node_dest"
298    }
299}
300
301
302
303proc dTree_copyRelevantBranch {dtree_source node_source dtree_dest node_dest} {
304    # This function acts like copyBranch except, it chooses only used nodes (dtree_source should be tmpTree ...)
305    upvar $dtree_source tree1
306    upvar $dtree_dest tree2
307    set nodeName [lindex $node_source end]
308    if {[dTree_nodeExists $tree2 "$node_dest $nodeName"]} {
309        dTree_rmBranch tree2 "$node_dest $nodeName"
310    }
311   
312    dTree_addNode tree2 "$node_dest" $nodeName
313    foreach attribute [dTree_getAttributes $tree1 $node_source] {
314        dTree_setAttribute tree2 "$node_dest $nodeName" [lindex $attribute 0] [lindex $attribute 1]
315    }
316   
317    foreach child [dTree_getUsedChildren $tree1 $node_source] {
318        dTree_copyRelevantBranch tree1 "$node_source $child" tree2 "$node_dest $nodeName"
319    }
320}
321
322
323proc dTree_copyRelevantBranch_ForpartialData {dtree_source node_source dtree_dest node_dest} {
324    # This function acts like copyBranch except, it chooses only used nodes (dtree_source should be tmpTree ...)
325    upvar $dtree_source tree1
326    upvar $dtree_dest tree2
327    set nodeName [lindex $node_source end]
328    #set nodeFather1 "[lrange $node_source 0 end-1]"
329    #set nodeFather2 "root [lrange $nodeFather1 2 end]"
330   
331   
332    # $tree1 donnes a charger
333    # $tree2 donnes cibles
334   
335    set node_source2 "$node_source"
336    if {[string match "item_*" $nodeName ]} {
337        set name1 "[dTree_getAttribute_fast $tree1 "$node_source" "value"]"
338        foreach item [dTree_getChildren_fast  $tree2 $node_dest] {
339            set name2 "[dTree_getAttribute_fast $tree2 "$node_dest $item" "value"]"
340            if {$name1 == $name2} {
341                set node_source2  "$node_dest $item"
342            }
343        }
344       
345    }
346    set nodeName2 [lindex $node_source2 end]
347   
348    # Attributes update
349    foreach attribute [dTree_getAttributes $tree1 $node_source] {
350        dTree_setAttribute tree2 "$node_dest $nodeName2" [lindex $attribute 0] [lindex $attribute 1]
351    }
352   
353    # Childs Update
354    foreach child [dTree_getChildren_fast $tree1 $node_source] {
355        dTree_copyRelevantBranch_ForpartialData tree1 "$node_source $child" tree2 "$node_dest $nodeName2"
356    }
357}
358
359
360
361
362
363proc dTree_moveBranch {dtree_source node_source dtree_dest node_dest} {
364    upvar $dtree_source tree1
365    upvar $dtree_dest tree2
366    dTree_copyBranch tree1 "$node_source" tree2 "$node_dest"
367    dTree_rmBranch tree1 "$node_source"
368}
369
370proc dTree_searchAddress {dtree pattern} {
371    set pattern "*[join [split $pattern { }] *]*"
372    set addresses ""
373    set result ""
374    dict for {node subdict} $dtree {
375        dict for {attr value} $subdict {
376            lappend addresses "$node $attr"
377        }
378    }
379    foreach address $addresses {
380        if {[string match -nocase $pattern $address]} {
381            lappend result $address
382        }
383    }
384   
385    return $result
386}
387
388proc dTree_searchNode {dtree pattern} {
389    # Two types of pattern can be read here :
390    #  -> One with no spaces, it's strict, the function will look for *pattern
391    #  -> If spaces in the pattern, the function searches for all addresses which
392    #     contain every element of the pattern in the order of the pattern
393   
394    if {[regexp {\s} $pattern]} {
395        set pattern [split $pattern { }]
396        set pattern "*[join [lrange $pattern 0 end-1] *]* [lindex $pattern end]"
397    } else {
398        set pattern "* [split $pattern {.}]"
399    }
400    set addresses ""
401    set result ""
402    dict for {node subdict} $dtree {
403        lappend addresses "$node"
404    }
405    foreach address $addresses {
406        if {[string match -nocase $pattern $address]} {
407            lappend result $address
408        }
409    }
410    return $result
411}
412
413proc dTree_searchNode_old {dtree pattern} {
414    set pattern "*$pattern"
415    set addresses ""
416    set result ""
417    dict for {node subdict} $dtree {
418        lappend addresses "$node"
419    }
420    foreach address $addresses {
421        if {[string match -nocase $pattern $address]} {
422            lappend result $address
423        }
424    }
425    return $result
426}
427
428proc dTree_nodeExists {tree key} {
429   
430    return [dict exists $tree $key]
431   
432}
433
434
435proc dTree_attrExists_fast {tree key attribute} {
436    if {[dict exists $tree "$key" $attribute]} {
437        return 1
438    } else {
439        return 0
440    }
441}
442
443proc dTree_attrExists {tree key attribute} {
444    if {[dict exists $tree "$key" $attribute]} {
445        return 1
446    } else {
447        if {[dict exists $tree "[dTree_cleanKey $key]" $attribute]} {
448            return 1
449        } else {
450            return 0
451        }
452    }
453}
454
455proc dTree_puts {args} {
456    set tree [lindex $args 0]
457    set node [lindex $args 1]
458    set indent [lindex $args 2]
459    if {$node == ""} {set node root}
460    puts "$indent ### [lindex $node end]"
461    foreach attr [dTree_getAttributes $tree "$node"] {
462        puts "$indent  > [lindex $attr 0]\t: [lindex $attr 1]"
463    }
464    set indent "$indent   "
465    foreach child [dTree_getChildren_fast $tree "$node"] {
466        dTree_puts $tree "$node $child" $indent
467    }
468}
469
470proc dTree_compareBranch {tree1 tree2 node relevantNodes listDifferentNodes} {
471    # This function compare two trees beginning from 'node'
472    # If the trees are identical, it returns 1
473    # If they are not, it returns 0 and the list of the nodes where the differences begin are stored in 'listDifferentNodes'
474    # In listDifferentNodes, the first element stores the nodes with a difference in the node (arguments are different)
475    # The second element stores the nodes existing in tree2 and not in tree1
476    # The third element stores the nodes existing in tree1 and not in tree2
477    # The fourth element stores the parents of the second and third ones (children are different)
478   
479    #Pour tester :
480#    set l "{} {} {}"
481#    puts [dTree_compareBranch $DStree $tmpTree "root" l]
482   
483#    foreach el [lindex $l 0] {puts "!= $el}   
484#    foreach el [lindex $l 1] {puts "++ $el}
485#    foreach el [lindex $l 2] {puts "-- $el}     
486   
487    #debug "Comparing $node "   
488    upvar $listDifferentNodes listNodes
489    if {$listNodes == ""} {set listNodes "{} {} {} {}"}
490    set status 1
491   
492    # Retrieve children list
493    if {$relevantNodes != 1} {
494        set children1 [lsort [dTree_getChildren $tree1 $node]]
495        set children2 [lsort [dTree_getChildren $tree2 $node]]
496    } else {
497        set children1 [lsort [dTree_getUsedChildren $tree1 $node]]
498        set children2 [lsort [dTree_getUsedChildren $tree2 $node]]       
499    }
500   
501    # Retrieve arguments
502    set attributes1 [lsort -index 0 [dTree_getAttributes $tree1 $node]]
503    set attributes2 [lsort -index 0 [dTree_getAttributes $tree2 $node]]
504   
505    # Compare, if not the same, return false, no need to test the children ...
506    if {$attributes1 != $attributes2 } {
507        #debug "attributes1 : $attributes1"
508        #debug "attributes2 : $attributes2"
509       
510        set tmpList [lindex $listNodes 0]
511        lappend tmpList "$node"
512        lset listNodes 0 $tmpList
513       
514        return 0
515    }   
516   
517    if { $children1 != $children2 } {
518 
519        set childrenToTest ""
520       
521        set tmpList [lindex $listNodes 3]
522        lappend tmpList "$node"
523        lset listNodes 3 $tmpList       
524       
525        foreach child $children1 {
526            if {$child ni $children2} {
527                set tmpList [lindex $listNodes 2]
528                lappend tmpList "$node $child"
529                lset listNodes 2 $tmpList               
530            } else {
531                lappend childrenToTest $child
532            }
533        }
534       
535        foreach child $children2 {
536            if {$child ni $children1} {
537                set tmpList [lindex $listNodes 1]
538                lappend tmpList "$node $child"
539                lset listNodes 1 $tmpList     
540               
541                # lremove
542                set idx [lsearch -exact $childrenToTest $child]
543                set childrenToTest [lreplace $childrenToTest $idx $idx]
544            }
545        }       
546       
547        foreach child $childrenToTest {
548            lappend childrenStatus [dTree_compareBranch $tree1 $tree2 "$node $child" $relevantNodes listNodes]
549        }       
550       
551        return 0   
552    }
553   
554    # If no children and status is 1, comparison is OK, return is possible
555    if {[llength $children1] == 0} {
556        return 1
557    } 
558   
559    # From now, nodes are the same and there are children (which are the same)
560    set childrenStatus ""
561    foreach child $children1 {
562        lappend childrenStatus [dTree_compareBranch $tree1 $tree2 "$node $child" $relevantNodes listNodes]
563    }
564   
565   
566    return [expr min([join $childrenStatus ,])]
567}
568
569#proc saveTree_old {file tree} {
570#    set fileId [open $file w]
571#    puts $fileId $tree
572#    close $fileId
573#}
574
575proc saveXMLnode {fileId tree currentSaveNode indentation} {
576    set indentation "$indentation    "
577   
578    # Calculates list of children to know if there are some
579    set childrenList [dTree_getChildren $tree $currentSaveNode]
580   
581    puts -nonewline $fileId "$indentation<[lindex $currentSaveNode end]"
582   
583    #foreach attribute write it
584    foreach attribute [dTree_getAttributes $tree $currentSaveNode] {
585        puts -nonewline $fileId " [lindex $attribute 0]=\"[lindex $attribute 1]\""
586    }
587   
588    # makes a simple element if no children
589    if {[llength $childrenList] == 0} {
590        puts -nonewline $fileId " /"
591    }
592    puts $fileId ">"
593   
594    #write the XMLContent
595   
596    #foreach child, add indentation, write child
597    foreach child $childrenList {
598        set childNode "$currentSaveNode $child"
599        saveXMLnode $fileId $tree $childNode $indentation
600    }
601   
602    #close tag
603    if {[llength $childrenList] > 0} {
604        puts $fileId "$indentation</[lindex $currentSaveNode end]>"
605    }
606   
607}
608
609
610
611#proc loadTree_old {file itree} {
612#    upvar $itree tree
613#    set fileId [open $file r]
614#    set result [read $fileId]
615#    close $fileId
616#    set tree $result
617#    #dict for {node subdict} $tree {
618#    #    dict for {attr value} $subdict {
619#    #        debug "\ngenerate <<treeChange-[join $node {.}].$attr>>"
620#    #        event generate . <<treeChange-[join $node {.}].$attr>>
621#    #    }
622#    #}
623#    event generate . <<InitializeGUI>>
624#}
625#
626#proc initializeNode {itree node} {
627#    upvar $itree tree
628#    global widgetInfo
629#    foreach child [dTree_getChildren $tree [join [split $node "."] " "]] {
630#        set address "[join $node .].$child"
631#       
632#        # Check if the child is a widget or a container
633#        if {[array names widgetInfo -exact "$address-require"] == ""} {
634#            #child is a container
635#            event generate . <<treeChange-$address>>
636#            initializeNode tree $address
637#           
638#        } else {
639#            #child is a widget
640#            if {$widgetInfo($address-require) == ""} {
641#                #child is an independant widget
642#               
643#                event generate . <<treeChange-$address>>
644#                initializeNode tree $address
645#            } else {
646#                initializeNode tree $widgetInfo($address-requirelist)
647#                initializeNode tree $address
648#            }
649#        }
650#       
651#
652#    }
653#}
654#
655#proc loadXMLProject {file} {
656#    global DStree
657#    global metaTree
658#    global loadedProject
659#    global widgetInfo
660#    global workingDir
661#    dTree_init loadTree
662#    dTree_init dummyTree   
663#   
664#   
665#   
666#}
667#
668#proc loadXMLDataset {file} {
669#   
670#}
671
672proc xml2tree {file itree xmlType} {
673   
674    upvar $itree tree
675    parseFile $file tree "" "DStree"   
676}
677
678proc csv2tree {file itree} {
679    upvar $itree tree
680   
681    # open file
682    set data [read [open $file]]
683    set data [split $data \n]
684   
685    # Foreach line
686    foreach line $data {
687       
688        set line [split $line ";"]
689        if {[string trim [lindex $line 0]] == ""} { continue}
690        # Create address
691        set addressNode "root [join [split [lindex $line 0] {.}] { }]"
692       
693        # Read attribute
694        set attr [join [lrange $line 1 end] ";"]
695       
696        # Create node
697        if {[catch {dTree_addNode tree [lrange $addressNode 0 end-1] [lindex $addressNode end]} fid]} {
698            error "Error reading the CSV file : Make sure all the parents of $addressNode have been set"
699        }
700       
701        # Add attribute
702        #if {$attr != ""} {
703            dTree_setAttribute tree $addressNode "value" "$attr"
704        #}
705    }
706}
707
708proc tree2xml {file tree} {
709    set fileId [open $file w]
710    puts $fileId {<?xml version="1.0" encoding="UTF-8"?>}
711    set indentation ""
712    # save the tree under the root node
713    set childrenList [dTree_getChildren $tree "root"]
714    foreach child $childrenList {
715        set childNode "root $child"
716        saveXMLnode $fileId $tree $childNode $indentation
717    }
718    close $fileId
719}
720
721proc tree2csv {args} {
722    if {[llength $args] == 3} {
723        set file [lindex $args 0]
724        set tree [lindex $args 1]
725        set node [lindex $args 2]
726    } elseif {[llength $args] == 2} {
727        set file [lindex $args 0]
728        set tree [lindex $args 1]
729        set node ""       
730    } else {
731        error "Error with arguments ([llength $args]) : $args"
732    }
733   
734    if {$node == ""} {
735        # Begin the process
736        set node root
737        set fileId [open $file w]
738       
739        set childrenList [dTree_getChildren $tree "root"]
740        foreach child $childrenList {
741            set childNode "root $child"
742            tree2csv $fileId $tree $childNode
743        }
744       
745        close $fileId
746    } else {
747        ###### recursive process
748       
749        # Write node
750        puts -nonewline $file "[join [lrange $node 1 end] {.}]"
751       
752        # Write attributes
753        foreach attribute [dTree_getAttributes $tree $node] {
754            puts -nonewline $file ";[lindex $attribute 1]"
755        }
756        puts $file ""
757       
758        # Write every child
759        set childrenList [dTree_getChildren $tree "$node"]
760        foreach child $childrenList {
761            set childNode "$node $child"
762            tree2csv $file $tree $childNode
763        }
764    }
765}
766
767
768#  Copyright CERFACS 2014
769#   
770#  antoine.dauptain@cerfacs.fr
771#   
772#  This software is a computer program whose purpose is to ensure technology
773#  transfer between academia and industry.
774#   
775#  This software is governed by the CeCILL-B license under French law and
776#  abiding by the rules of distribution of free software.  You can  use,
777#  modify and/ or redistribute the software under the terms of the CeCILL-B
778#  license as circulated by CEA, CNRS and INRIA at the following URL
779#  "http://www.cecill.info".
780#   
781#  As a counterpart to the access to the source code and  rights to copy,
782#  modify and redistribute granted by the license, users are provided only
783#  with a limited warranty  and the software's author,  the holder of the
784#  economic rights,  and the successive licensors  have only  limited
785#  liability.
786#   
787#  In this respect, the user's attention is drawn to the risks associated
788#  with loading,  using,  modifying and/or developing or reproducing the
789#  software by the user in light of its specific status of free software,
790#  that may mean  that it is complicated to manipulate,  and  that  also
791#  therefore means  that it is reserved for developers  and  experienced
792#  professionals having in-depth computer knowledge. Users are therefore
793#  encouraged to load and test the software's suitability as regards their
794#  requirements in conditions enabling the security of their systems and/or
795#  data to be ensured and,  more generally, to use and operate it in the
796#  same conditions as regards security.
797#   
798#  The fact that you are presently reading this means that you have had
799#  knowledge of the CeCILL-B license and that you accept its terms.
Note: See TracBrowser for help on using the repository browser.