home *** CD-ROM | disk | FTP | other *** search
/ PC World 1998 October / PCWorld_1998-10_cd.bin / software / prehled / komix / DATA.Z / ada_class.tcl < prev    next >
Text File  |  1997-10-20  |  26KB  |  999 lines

  1. ###########################################################################
  2. ##
  3. ##  Copyright (c) 1996 by Cadre Technologies Inc.
  4. ##                          and Scientific Toolworks Inc.
  5. ##
  6. ##  This software is furnished under a license and may be used only in
  7. ##  accordance with the terms of such license and with the inclusion of
  8. ##  the above copyright notice. This software or any other copies thereof
  9. ##  may not be provided or otherwise made available to any other person.
  10. ##  No title to and ownership of the software is hereby transferred.
  11. ##
  12. ##  The information in this software is subject to change without notice
  13. ##  and should not be construed as a commitment by Cadre Technologies Inc.
  14. ##  or Scientific Toolworks Inc.
  15. ##
  16. ###########################################################################
  17. # Version 6.1.5 - 9/25/97
  18. # Handled case of class created with Ada95 as target language and "private
  19. # extension" as visibility.
  20.  
  21. # Needed for E_FILE_OPEN_WRITE
  22. #
  23. require cgen_msg.tcl
  24. require a83genmsg.tcl
  25.  
  26. global ada_hdr_sections
  27. set ada_hdr_sections {
  28.     h_hdr_sect
  29.     h_user_sect_1
  30.     h_incl_sect
  31.     h_class_nm_sect
  32.     h_user_sect_2
  33.     h_pub_data_sect
  34.     h_conv_func_sect
  35.     h_pub_access_sect
  36.     h_pub_func_sect
  37.     h_priv_data_sect
  38.     h_static_data_sect
  39.     h_priv_access_sect
  40.     h_priv_func_sect
  41.     h_user_sect_3
  42.     h_trailer_sect
  43.     h_user_sect_4
  44. }    
  45.  
  46.  
  47. global ada_src_sections
  48. set ada_src_sections {
  49.     c_hdr_sect
  50.     c_user_sect_1
  51.     c_conv_incl_sect
  52.     c_class_nm_sect
  53.     c_user_sect_2
  54.     c_opaque_sect
  55.     c_static_data_sect
  56.     c_user_sect_3
  57.     c_conv_func_sect
  58.     c_access_func_sect
  59.     c_impl_sect
  60.     c_user_sect_4
  61.     c_trailer_sect
  62.     c_user_sect_5
  63. }
  64.  
  65.  
  66. global ada_assoc_sections
  67. set ada_assoc_sections {
  68.     h_hdr_sect
  69.     h_user_sect_1
  70.     h_inter_pkg_sect
  71.     h_user_sect_2
  72. }
  73.  
  74.  
  75. global ada_link_sections
  76. set ada_link_sections {
  77.     h_sect
  78.     c_sect
  79. }
  80.  
  81. global ada_separate_sections
  82. set ada_separate_sections {
  83.     c_hdr_sect
  84.     c_user_sect_1
  85.     c_sep_line_sect
  86.     c_impl_sect
  87. }
  88.  
  89. # Global section array
  90. #
  91. global ada_sections
  92. global assoc_sections
  93. global separate_sections
  94. global link_sections
  95.  
  96. # Determine the right section based on the accessibility specification and
  97. # whether it is for reading or writing
  98. #
  99. proc get_hdr_sect {access {mode ""}} {
  100.     case [split_access_mode $access $mode] in {
  101.     {Public} {
  102.         return $ada_sections(h_pub_access_sect)
  103.     }
  104.     {Private} {
  105.         return $ada_sections(h_priv_access_sect)
  106.     }
  107.     {None} {
  108.         return $ada_sections(dev_null_sect)
  109.     }}
  110.     return $ada_sections(h_pub_access_sect)
  111. }
  112.  
  113. proc get_src_sect {access {mode ""}} {
  114.     case [split_access_mode $access $mode] in {
  115.     {Public} {
  116.         echo "SOURCE (mode=$mode) access is Public\n"
  117.         return 1;
  118.     }
  119.     {Private} {
  120.         echo "attrib access is Private\n"
  121.         return 1;
  122.     }
  123.     {None} {
  124.         echo "SOURCE (mode=$mode) access is None\n"
  125.         return 0;
  126.     }}
  127.     return 0;
  128. }
  129.  
  130.  
  131. # Determine the type of header section based on the accessibility specification and
  132. # whether it is for reading or writing
  133.  
  134.  
  135. proc get_hdr_type {access {mode ""}} {
  136.         return [split_access_mode $access $mode]
  137. }
  138.  
  139.  
  140.  
  141. # Split up the access mode and return the right part of it
  142. #
  143. proc split_access_mode {access mode} {
  144.     if {$access == ""} {
  145.         return Public
  146.     }
  147.     set rw_ac_list [split $access -]
  148.     if {[llength $rw_ac_list] == 2} {
  149.         if {$mode == "r"} {
  150.             return [lindex $rw_ac_list 0]
  151.         }
  152.         return [lindex $rw_ac_list 1]
  153.     }
  154.     return $access
  155. }
  156.  
  157. proc split_op_list_entry {access mode} {
  158.     set rw_ac_list [split $access :]
  159.     if {[llength $rw_ac_list] == 2} {
  160.         if {$mode == "class"} {
  161.             return [lindex $rw_ac_list 0]
  162.         }
  163.         return [lindex $rw_ac_list 1]
  164.     }
  165.     return $access
  166. }
  167.  
  168. # Determine the section for an assoc accesser function based on
  169. # the attribute "assoc_access"
  170. #
  171. proc get_assoc_hdr_sect {assoc {mode ""}} {
  172.     return [get_hdr_sect [get_assoc_access $assoc] $mode]
  173. }
  174.  
  175. proc get_assoc_src_sect {assoc {mode ""}} {
  176.     return [get_src_sect [get_assoc_access $assoc] $mode]
  177. }
  178.  
  179. # Determine the section for an attribute accesser function based on
  180. # the attribute "attrib_access"
  181. #
  182. proc get_attrib_hdr_sect {attrib {mode ""}} {
  183.     return [get_hdr_sect [get_attrib_access $attrib] $mode]
  184. }
  185.  
  186. proc get_attrib_src_sect {attrib {is_inline 0} {mode ""}} {
  187.     return [get_src_sect [get_attrib_access $attrib] $mode]
  188. }
  189.  
  190. #Determine the type of header section. "Private", "Public" or "None" is returned.
  191. proc get_attrib_hdr_type {attrib {mode ""}} {
  192.     return [get_hdr_type [get_attrib_access $attrib] $mode]
  193. }
  194.  
  195. proc get_assoc_hdr_type {attrib {mode ""}} {
  196.     return [get_hdr_type [get_assoc_access $attrib] $mode]
  197. }
  198.  
  199.  
  200. # Determine the type of a given section.  "hdr" or "src" is returned.
  201. # Special sections "hdr" and "src" are understood, and are returned as is.
  202. #
  203. proc determine_sect_type {sect} {
  204.     if {$sect == "src"} {
  205.         set type "src"
  206.     } elseif {$sect == "hdr"} {
  207.         set type "hdr"
  208.     } else {
  209.     global ada_sections
  210.         foreach n [array names ada_sections] {
  211.             if {$ada_sections($n) == $sect} {
  212.                 if {[lsearch $ada_src_sections $n] != -1} {
  213.                     set type "src"
  214.                 } else {
  215.                     set type "hdr"
  216.                 }
  217.                 break
  218.             }
  219.         }
  220.     }
  221.     return $type
  222. }
  223.  
  224. proc get_data_section {class} {
  225.     case [get_class_vis $class] in {
  226.     {Public} {
  227.         return $ada_sections(h_pub_data_sect)
  228.     }
  229.     {Private} {
  230.         return $ada_sections(h_priv_data_sect)
  231.     }
  232.     {Limited} {
  233.         return $ada_sections(h_priv_data_sect)
  234.     }
  235.     {Opaque} {
  236.         return $ada_sections(c_opaque_sect)
  237.     }}
  238.     return $ada_sections(h_pub_data_sect)
  239. }
  240.  
  241.  
  242. proc get_func_section {oper} {
  243.     case [get_method_access $oper] in {
  244.     {Public} {
  245.         return $ada_sections(h_pub_func_sect)
  246.     }
  247.     {Private} {
  248.         return $ada_sections(h_priv_func_sect)
  249.     }
  250.     {} {
  251.         return $ada_sections(h_pub_func_sect)
  252.     }}
  253. }
  254.  
  255. proc get_include_section {class} {
  256.     #
  257.     #if {[get_class_visibility $class] != "Opaque"} {
  258.     #    return $ada_sections(h_incl_sect)
  259.     #} else {
  260.     #    return $ada_sections(c_hdr_sect)
  261.     #}
  262.     #
  263.     return $ada_sections(h_incl_sect)
  264. }
  265.  
  266.  
  267.  
  268. # Create ada sections
  269. #
  270. proc create_ada_sections {sects} {
  271.     global ada_sections
  272.     foreach sect $sects {
  273.         set ada_sections($sect) [section create]
  274.         section set_indent $ada_sections($sect) 0 "    "
  275.     }
  276.     set ada_sections(dev_null_sect) [section create]
  277. }
  278.  
  279. proc create_assoc_sections {sects} {
  280.     global assoc_sections
  281.     foreach sect $sects {
  282.         set assoc_sections($sect) [section create]
  283.         section set_indent $assoc_sections($sect) 0 "    "
  284.     }
  285.     set assoc_sections(dev_null_sect) [section create]
  286. }
  287.  
  288. proc create_separate_sections {sects} {
  289.     global separate_sections
  290.     foreach sect $sects {
  291.         set separate_sections($sect) [section create]
  292.         section set_indent $separate_sections($sect) 0 "    "
  293.     }
  294.     set separate_sections(dev_null_sect) [section create]
  295. }
  296.  
  297. proc get_class_vis {class} {
  298.     set class_visibility [get_class_visibility $class]
  299.     if {$class_visibility == ""} {set class_visibility Public}
  300.     return $class_visibility
  301. }
  302.  
  303. # give sections their initial contents
  304.  
  305. proc init_ada_sections {name data_sect visibility} {
  306.     global USERMETHCMMT
  307.  
  308.     section append $ada_sections(h_incl_sect) "with $sysfile_name;\n"
  309.     section set_indent $ada_sections(h_user_sect_2) +
  310.     section set_indent $ada_sections(h_pub_data_sect) +
  311.     section set_indent $ada_sections(h_conv_func_sect) +
  312.     section set_indent $ada_sections(h_pub_func_sect) +
  313.     section set_indent $ada_sections(h_pub_access_sect) +
  314.     section set_indent $ada_sections(h_priv_access_sect) +
  315.     section set_indent $ada_sections(h_priv_func_sect) +
  316.     section set_indent $ada_sections(h_user_sect_3) +
  317.  
  318.     section append $ada_sections(h_priv_data_sect) "private\n\n"
  319.     section set_indent $ada_sections(h_priv_data_sect) +
  320.     section set_indent $ada_sections(h_static_data_sect) +
  321.  
  322.     #HM added comments to devide sections
  323.     section append $ada_sections(h_pub_func_sect) $USERMETHCMMT
  324.     section append $ada_sections(h_pub_func_sect) "\n"
  325.     section append $ada_sections(h_priv_func_sect) $USERMETHCMMT
  326.     section append $ada_sections(h_priv_func_sect) "\n"
  327.  
  328.     if {$visibility != "Opaque"} {
  329.         section append $data_sect "type $g_record_name is record\n"
  330.     }
  331.     section set_indent $data_sect +
  332.     section set_indent $ada_sections(c_user_sect_2) +
  333.     section set_indent $ada_sections(c_opaque_sect) +
  334.     section set_indent $ada_sections(c_static_data_sect) +
  335.     section set_indent $ada_sections(c_user_sect_3) +
  336.     section set_indent $ada_sections(c_conv_func_sect) +
  337.     section set_indent $ada_sections(c_access_func_sect) +
  338.     section set_indent $ada_sections(c_impl_sect) +
  339.     section set_indent $ada_sections(c_user_sect_4) +
  340.     section append $ada_sections(c_trailer_sect) "\nend $name;\n"
  341. }
  342.  
  343. proc init_sys_sections {name} {
  344.     section append $ada_sections(h_hdr_sect) \
  345.          "-- Specification file for ${name}\n\n"
  346.     section append $ada_sections(h_class_nm_sect) "package $name is\n"
  347.     section append $ada_sections(h_pub_data_sect) "\n"
  348.     section set_indent $ada_sections(h_user_sect_2) +
  349.     section set_indent $ada_sections(h_pub_data_sect) +
  350.     section set_indent $ada_sections(h_user_sect_3) +
  351.     section append $ada_sections(h_trailer_sect) "\nend $name;\n"
  352. }
  353.  
  354. proc init_poly_sections {class} {
  355.     set name [get_name $class]
  356.     section append $ada_sections(h_hdr_sect) \
  357.         "-- Specification file for ${g_poly_prefix}${name}\n\n"
  358.     section append $ada_sections(c_hdr_sect) \
  359.         "-- Body file for ${g_poly_prefix}${name}\n\n"
  360.     section append $ada_sections(h_incl_sect) "with $sysfile_name;\n"
  361.     set head_sect $ada_sections(h_class_nm_sect)
  362.     section append $ada_sections(c_class_nm_sect) "package body ${g_poly_prefix}${name} is\n\n"
  363.  
  364.     set data_sect $ada_sections(h_pub_data_sect)
  365.  
  366.     section append $head_sect "package ${g_poly_prefix}${name} is\n"
  367.     section append $head_sect "    type Kind is ("
  368.  
  369.     section set_indent $data_sect +
  370.     section append $data_sect "type $g_record_name (${name}_Kind: Kind := A_${name}) is record\n"
  371.     section set_indent $data_sect +
  372.     section append $data_sect "case ${name}_Kind is\n"
  373.  
  374.     section set_indent $ada_sections(h_pub_func_sect) +
  375.     section set_indent $ada_sections(c_impl_sect) +
  376.     section set_indent $ada_sections(h_pub_access_sect) +
  377.     section set_indent $ada_sections(c_access_func_sect) +
  378. }
  379.  
  380. # give sections their terminal contents
  381.  
  382. proc exit_ada_sections {class} {
  383.     global ada_sections g_assoc_list g_handle_name g_record_name
  384.     global g_component_count 
  385.  
  386.     set sect [get_data_section $class]
  387.     if {[get_class_visibility $class] != "Opaque"} {
  388.         if {$g_component_count == 0} {
  389.             section append $sect "null;\n"
  390.         }
  391.         section set_indent $sect -
  392.         section append $sect "end record;\n\n"
  393.         section append $ada_sections(h_static_data_sect) "\n"
  394.  
  395.         # Add the line "type Link is access Instance;" (defaults) if
  396.         # this class is the object of an association.  Opaque packages
  397.         # already contain this line.
  398.         #
  399. #        if {[lsearch $g_assoc_list [get_name $class]] != -1} {
  400. #            section append $ada_sections(h_pub_data_sect) \
  401. #                "type $g_handle_name is access $g_record_name;\n\n"
  402. #        }
  403.  
  404.         # Add it all of the time... In case a class is used as a type 
  405.         # within another class.
  406.         section append $ada_sections(h_pub_data_sect) \
  407.             "type $g_handle_name is access $g_record_name;\n\n"
  408.     } else {
  409.         if {$g_component_count == 0}  {
  410.            section append $ada_sections(c_opaque_sect) "null;\n"
  411.         }
  412.         section set_indent $ada_sections(c_opaque_sect) -
  413.         section append $ada_sections(c_opaque_sect) "end record;\n\n"
  414.         section append $ada_sections(c_static_data_sect) "\n"
  415.     }
  416.  
  417.     set tmp_sect [section create]
  418.     section append_section $tmp_sect $ada_sections(h_priv_data_sect)
  419.     section append_section $tmp_sect $ada_sections(h_priv_access_sect)
  420.     section append_section $tmp_sect $ada_sections(h_priv_func_sect)
  421.     section append_section $tmp_sect $ada_sections(h_static_data_sect)
  422.  
  423.     echo "private section = [section get_contents $tmp_sect]..."
  424.     if {[section get_contents $tmp_sect] == "private\n\n\n" } {
  425.         set ada_sections(h_priv_data_sect) [section create]
  426.     }
  427.     section append $ada_sections(h_user_sect_2) "\n"
  428. }
  429.  
  430. proc exit_poly_sections {class} {
  431.     global g_handle_name
  432.     global g_record_name
  433.  
  434.     section append $ada_sections(h_class_nm_sect) ");\n"
  435.  
  436.     section append $ada_sections(h_pub_data_sect) "end case;\n"
  437.     section set_indent $ada_sections(h_pub_data_sect) -
  438.     section append $ada_sections(h_pub_data_sect) "end record;\n\n"
  439.     section append $ada_sections(h_pub_data_sect) "type $g_handle_name is access $g_record_name;\n\n"
  440.  
  441.     section set_indent $ada_sections(h_pub_func_sect) -
  442.     section append $ada_sections(h_pub_func_sect) "end ${g_poly_prefix}[get_name $class];\n"
  443.  
  444.     section set_indent $ada_sections(c_impl_sect) -
  445.     section append $ada_sections(c_trailer_sect) "end ${g_poly_prefix}[get_name $class];\n"
  446. }
  447.  
  448. #
  449. # Dependency management. If there is only one target (lib or exe) in the
  450. # system then source files are automatically added to the dependency list
  451. # of that target.
  452. #
  453.  
  454. global the_only_target
  455. set the_only_target [fstorage::dir {exe lib}]
  456. if {[llength $the_only_target] == 1} {
  457.     global the_only_target_deps
  458.     foreach dep [fstorage::get_dependencies $the_only_target] {
  459.         set the_only_target_deps($dep) 1
  460.     }
  461. } else {
  462.     catch {unset the_only_target}
  463. }
  464.  
  465. proc add_only_target_dep {dep} {
  466.     if {[info exists the_only_target] &&
  467.         ![info exists the_only_target_deps($dep)]} {
  468.         fstorage::add_dependency $the_only_target $dep
  469.         set the_only_target_deps($dep) 1
  470.     }
  471. }
  472.  
  473. # Write the sections to the right file and deallocate them
  474. #
  475. proc write_ada_sections {class hsects csects} {
  476.     set class_name [get_name $class]
  477.     class2tgtfiles $class_name src_file h_file
  478.     #HM do not write the body file if the spec file doesn't change
  479.     set do_write 1
  480.     if {[do_write_sections $class_name $h_file $hsects 1 1] == 2}  {
  481.        set do_write 0
  482.     }
  483.     do_write_sections $class_name $src_file $csects 1 $do_write
  484.     section dealloc $ada_sections(dev_null_sect)
  485.     unset ada_sections(dev_null_sect)
  486. }
  487.  
  488. proc write_poly_sections {class hsects csects} {
  489.     class2polyfiles $class src_file h_file
  490.     set class_name [get_name $class]
  491.     if {[is_file_regenerated $h_file] || [is_file_regenerated $src_file]} {
  492.         puts stdout "Generating for polymorphic class '${g_poly_prefix}[get_name $class]'"
  493.             #HM do not write the body file if the spec file doesn't change
  494.         set do_write 1
  495.         if {[do_write_sections $class_name $h_file $hsects 4 1] == 2}  {
  496.            set do_write 0
  497.         }
  498.         do_write_sections $class_name $src_file $csects 4 $do_write
  499.     }
  500. }
  501.  
  502. proc write_assoc_sections {class hsects ext} {
  503.     class2assocfiles $class $ext h_file
  504.     set class_name [get_name $class]
  505.     do_write_sections $class_name $h_file $hsects 0 1
  506. }
  507.  
  508. proc write_link_sections {class hsects csects} {
  509.     class2linkfiles $class src_file h_file
  510.     set class_name [get_name $class]
  511.     #HM do not write the body file if the spec file doesn't change
  512.     set do_write 1
  513.     if {[do_write_sections $class_name $h_file $hsects 3 1] == 2}  {
  514.        set do_write 0
  515.     }
  516.     do_write_sections $class_name $src_file $csects 3 $do_write
  517. }
  518.  
  519. proc write_sys_sections {name hsects} {
  520.     class2tgtfiles $name c_file h_file
  521.     if {[is_file_regenerated $h_file]} {
  522.         puts stdout "Generating for User-Defined Types File '$sysfile_name'"
  523.         do_write_sections $name $h_file $hsects 5 1
  524.     }
  525. }
  526.  
  527. proc write_separate_sections {class csects ext} {
  528.     class2separatefiles $class $ext c_file
  529.     set class_name [get_name $class]
  530.     do_write_sections $class_name $c_file $csects 2 1
  531.  
  532. }
  533.  
  534.  
  535. proc is_file_regenerated {filename} {
  536.     global skip_file
  537.     global gen_file
  538. #    if {[llength $sects] == 0} {return 0}
  539.     if {[info exists gen_file($filename)] ||
  540.         ($import_new && ![info exists skip_file($filename)])} {
  541.         return 1
  542.     }
  543.     return 0
  544. }
  545.  
  546. proc do_write_sections {class_name file_name sects flag do_write} {
  547.     set did_save_file 0
  548.     if {[llength $sects] == 0} {return $did_save_file}
  549.     set nt $file_name
  550.     global skip_file
  551.     global gen_file
  552.     if {[info exists gen_file($nt)] ||
  553.         ($import_new && ![info exists skip_file($nt)])} {
  554.         set cmp_sect [section create]
  555.         foreach sect $sects {
  556.             case $flag in {
  557.             {0} {set sect2 $assoc_sections($sect)}
  558.             {1} {set sect2 $ada_sections($sect)}
  559.             {2} {set sect2 $separate_sections($sect)}
  560.             {3} {set sect2 $link_sections($sect)}
  561.             {4} {set sect2 $ada_sections($sect)}
  562.             {5} {set sect2 $ada_sections($sect)}
  563.             }
  564.             section append_section $cmp_sect $sect2
  565.             section dealloc $sect2
  566.             unset sect2
  567.         }
  568.         if {[section_equals_file $cmp_sect $nt] || $do_write == 0} {
  569.             puts "   $nt has not changed: file not written"
  570.             section dealloc $cmp_sect
  571.             return 2
  572.         }
  573.         puts stdout "   Creating $nt"
  574.         if {[catch {set fd [fstorage::open $nt w]} reason]} {
  575.             puts stderr $reason
  576.             m4_error $E_FILE_OPEN_WRITE $nt
  577.         } else {
  578.             if { [catch {fstorage::set_imp_from $nt $class_name} \
  579.                   reason] } {
  580.                 puts stderr $reason
  581.             }
  582.             section write $cmp_sect $fd
  583.             section dealloc $cmp_sect
  584.             fstorage::close $fd
  585.             set did_save_file 1
  586.         }
  587.     }
  588.     return $did_save_file
  589. }
  590.  
  591. proc process_external_class_source {class} {
  592.     set class_name [get_name $class]
  593.     set tmp_sect [section create]
  594.     expand_text $tmp_sect [get_class_source $class]
  595.     set files [string trim [section get_contents $tmp_sect]]
  596.     section dealloc $tmp_sect
  597.  
  598.     set first 1
  599.     foreach entry [split $files ,] {
  600.         # first one is hplus_type
  601.         # all others are ada_type
  602.         if $first {
  603.             set first 0
  604.             set ftype $ada_spec_type
  605.         } else {
  606.             set ftype $ada_body_type
  607.         }
  608.         set file_name [class2file $class_name]
  609.         set nt ${file_name}.$ftype
  610.         global skip_file
  611.         global gen_file
  612.         if {[info exists gen_file($nt)] ||
  613.             ($import_new && ![info exists skip_file($nt)])} {
  614.             set fullpath [find_file $entry]
  615.             if {$fullpath == ""} {
  616.                 m4_error $E_NOEXTCLASSSOURCE [get_name $class] $entry
  617.                 continue
  618.             }
  619.             puts "Importing external '$fullpath'"
  620.             puts "   Creating $nt"
  621.             if {[catch {set out [fstorage::open $nt w]} reason]} {
  622.                 puts stderr $reason
  623.                 m4_error $E_FILE_OPEN_WRITE $nt
  624.             } else {
  625.                 if { [catch {fstorage::set_imp_from $nt \
  626.                     $class_name} reason] } {
  627.                     puts stderr $reason
  628.                 }
  629.                 set max 8092
  630.                 set in [open $fullpath r]
  631.                 while {[set result [read $in $max]] != ""} {
  632.                     puts -nonewline $out $result 
  633.                 }
  634.                 close $in
  635.                 fstorage::close $out
  636.             }
  637.         }
  638.     }
  639. }
  640.  
  641. # find file using global 'exsrc_searchpath'
  642.  
  643. proc find_file {file} {
  644.     if [file exists $file] {
  645.         return $file
  646.     }
  647.     global exsrc_searchpath
  648.     if {! [info exists exsrc_searchpath]} {
  649.         return ""
  650.     }
  651.     foreach dir [split $exsrc_searchpath :] {
  652.         set fullpath $dir/$file
  653.         if [file exists $fullpath] {
  654.             return $fullpath
  655.         }
  656.     }
  657.     return ""
  658. }
  659.  
  660. # read status arrays and generate 'only-once' code
  661.  
  662. proc gen_delayed_code {} {
  663.     global ada_hdr_incs
  664.     catch {unset cpp_hdr_incs}
  665.     global cpp_hdr_files
  666.     catch {unset cpp_hdr_files}
  667. }
  668.  
  669. # Global friend array
  670. #
  671. global cpp_friends
  672.  
  673. proc add_friend {friend} {
  674.     global cpp_friends
  675.     set cpp_friends([get_name $friend]) 1
  676. }
  677.  
  678. proc gen_friends {} {
  679.     global cpp_friends
  680.     if {![info exists cpp_friends]} {
  681.         return
  682.     }
  683.     set sect $ada_sections(h_friend_sect)
  684.     section set_indent $sect +
  685.     foreach class [lsort [array names cpp_friends]] {
  686.         section append $sect "friend class $class;\n"
  687.     }
  688.     section set_indent $sect +
  689.     unset cpp_friends
  690. }
  691.  
  692. #
  693. # forward declaration / class header inclusion management functions
  694. #
  695.  
  696. # Global arrays to store the information
  697. #
  698. global cpp_forwards
  699. global cpp_hdr_incs cpp_hdr_incs_name cpp_hdr_incs_name_ext
  700. global cpp_src_incs cpp_src_incs_name cpp_src_incs_name_ext
  701.  
  702. proc add_forward {class} {
  703.     global cpp_forwards
  704.     set cpp_forwards([get_name $class]) $class
  705. }
  706.  
  707. proc add_forward_name {name} {
  708.     global cpp_forwards
  709.     set cpp_forwards($name) 1
  710. }
  711.  
  712. proc add_hdr_inc {class} {
  713.     global cpp_hdr_incs
  714.     set cpp_hdr_incs([get_name $class]) $class
  715. }
  716.  
  717. proc add_hdr_inc_name {class_name {ext "hxx"}} {
  718.     global cpp_hdr_incs_name cpp_hdr_incs_name_ext
  719.     set cpp_hdr_incs_name($class_name) 1
  720.     set cpp_hdr_incs_name_ext($class_name) $ext
  721. }
  722.  
  723. proc add_src_inc {class} {
  724.     global cpp_src_incs
  725.     set cpp_src_incs([get_name $class]) $class
  726. }
  727.  
  728. proc add_src_inc_name {class_name {ext "hxx"}} {
  729.     global cpp_src_incs_name cpp_src_incs_name_ext
  730.     set cpp_src_incs_name($class_name) 1
  731.     set cpp_src_incs_name_ext($class_name) $ext
  732. }
  733.  
  734. # Generate forwards. If the class definition is also included, the forward
  735. # is not generated.
  736. #
  737. proc gen_forwards {} {
  738.     global cpp_forwards cpp_hdr_incs
  739.     if {![info exists cpp_forwards]} {
  740.         return
  741.     }
  742.     set sect $ada_sections(h_fwd_decl_sect)
  743.     foreach class [lsort [array names cpp_forwards]] {
  744.         if [info exists cpp_hdr_incs($class)] {
  745.             continue
  746.         }
  747.     }
  748.     unset cpp_forwards
  749. }
  750.  
  751. proc gen_hdr_incs {class} {
  752.     set user_include_list ""
  753.     set incls [get_include_list $class]
  754.     echo "incls = $incls"
  755.     if {$incls != ""} {
  756.         foreach incl [config_include_list [split $incls ,]] {
  757.             lappend user_include_list $incl
  758.         }
  759.     }
  760.     # do not sort ! remove duplicates
  761.     foreach entry $user_include_list {
  762.         if [info exists dup($entry)] {
  763.             continue;
  764.         }
  765.         set dup($entry) 1
  766.         section append $ada_sections(h_incl_sect) "with $entry;\n"
  767.     }
  768. }
  769.  
  770. # Generate includes for source file. Don't generate if the file is already
  771. # included in the header file.
  772. #
  773. proc gen_src_incs {} {
  774.     global cpp_src_incs cpp_src_incs_name cpp_src_incs_name_ext cpp_hdr_files
  775.     if {! [info exists ada_sections(c_hdr_sect)]} {
  776.         catch {unset cpp_src_incs}
  777.         catch {unset cpp_src_incs_name}
  778.         catch {unset cpp_src_incs_name_ext}
  779.  
  780.         return
  781.     }
  782.     set gen_include_list ""
  783.     set user_include_list ""
  784.     if [info exists cpp_src_incs] {
  785.         foreach class [array names cpp_src_incs] {
  786.             if [info exists cpp_hdr_incs($class)] {
  787.                 continue
  788.             }
  789.             set hdl $cpp_src_incs($class)
  790.             set incls [get_include_list $hdl]
  791.             if {$incls == ""} {
  792.                 lappend gen_include_list [get_name $hdl]
  793.                 set src_files([h_class2file $class]) 1
  794.             } else {
  795.                 foreach incl [config_include_list [split $incls ,]] {
  796.                     if [info exists cpp_hdr_files($incl)] {
  797.                         continue
  798.                     }
  799.                     lappend user_include_list $incl
  800.                     set src_files($incl) 1
  801.                 }
  802.             }
  803.         }
  804.     }
  805.     if [info exists cpp_src_incs_name] {
  806.         foreach entry [array names cpp_src_incs_name] {
  807.             set file [h_class2file $entry $cpp_src_incs_name_ext($entry)]
  808.             if [info exists cpp_hdr_files($file)] {
  809.                 continue
  810.             }
  811.             if [info exists src_files($file)] {
  812.                 continue
  813.             }
  814.             lappend gen_include_list $entry
  815.         }
  816.     }
  817.     foreach entry [lsort $gen_include_list] {
  818.                 if {[info exists cpp_src_incs_name_ext($entry)]} {
  819.                     set ext $cpp_src_incs_name_ext($entry)
  820.                 } else {
  821.                     set ext "hxx"
  822.                 }
  823.         # prefer user includes
  824.         set idx [lsearch -exact $user_include_list [h_class2file $entry $ext]]
  825.         if {$idx == -1} {
  826.             gen_include $entry $ada_sections(c_hdr_sect) $ext
  827.         }
  828.     }
  829.     catch {unset cpp_src_incs}
  830.     catch {unset cpp_src_incs_name}
  831.     catch {unset cpp_src_incs_name_ext}
  832.     catch {unset src_files}
  833. }
  834.  
  835. # Template emulation management
  836.  
  837. # Sets to be instantiated
  838. #
  839. global cpp_sets
  840.  
  841. proc instantiate_set {class} {
  842.     if $has_templates {
  843.         return
  844.     }
  845.     global cpp_sets
  846.     set cpp_sets($class) 1
  847. }
  848.  
  849. proc gen_sets {} {
  850.     global cpp_sets
  851.     if {![info exists cpp_sets]} {
  852.         return
  853.     }
  854.     set sect $ada_sections(h_incl_sect)
  855.     foreach class [lsort [array names cpp_sets]] {
  856.         gen_set_type_def $class $sect
  857.     }
  858.     unset cpp_sets
  859. }
  860.  
  861. # Ordered Sets to be instantiated
  862. #
  863. global cpp_osets
  864.  
  865. proc instantiate_oset {class} {
  866.     if $has_templates {
  867.         return
  868.     }
  869.     global cpp_osets
  870.     set cpp_osets($class) 1
  871. }
  872.  
  873. proc gen_osets {} {
  874.     global cpp_osets
  875.     if {![info exists cpp_osets]} {
  876.         return
  877.     }
  878.     set sect $ada_sections(h_incl_sect)
  879.     foreach class [lsort [array names cpp_osets]] {
  880.         gen_oset_type_def $class $sect
  881.     }
  882.     unset cpp_osets
  883. }
  884.  
  885. # Dicts to be instantiated
  886. #
  887. global cpp_dicts
  888.  
  889. proc instantiate_dict {key value} {
  890.     if $has_templates {
  891.         return
  892.     }
  893.     global cpp_dicts
  894.     set cpp_dicts($key,$value) 1
  895. }
  896.  
  897. proc gen_dicts {} {
  898.     global cpp_dicts
  899.     if {![info exists cpp_dicts]} {
  900.         return
  901.     }
  902.     set sect $ada_sections(h_incl_sect)
  903.     foreach keyval [lsort [array names cpp_dicts]] {
  904.         set kv_list [split $keyval ,]
  905.         gen_dict_type_def [lindex $kv_list 0] [lindex $kv_list 1] $sect
  906.     }
  907.     unset cpp_dicts
  908. }
  909.  
  910. # Set Dicts to be instantiated
  911. #
  912. global cpp_set_dicts
  913.  
  914. proc instantiate_set_dict {key value} {
  915.     if $has_templates {
  916.         return
  917.     }
  918.     global cpp_set_dicts
  919.     set cpp_set_dicts($key,$value) 1
  920. }
  921.  
  922. proc gen_set_dicts {} {
  923.     global cpp_set_dicts
  924.     if {![info exists cpp_set_dicts]} {
  925.         return
  926.     }
  927.     set sect $ada_sections(h_incl_sect)
  928.     foreach keyval [lsort [array names cpp_set_dicts]] {
  929.         set kv_list [split $keyval ,]
  930.         gen_set_dict_type_def [lindex $kv_list 0] \
  931.                 [lindex $kv_list 1] $sect
  932.     }
  933.     unset cpp_set_dicts
  934. }
  935.  
  936. # Ordered Set Dicts to be instantiated
  937. #
  938. global cpp_oset_dicts
  939.  
  940. proc instantiate_oset_dict {key value} {
  941.     if $has_templates {
  942.         return
  943.     }
  944.     global cpp_oset_dicts
  945.     set cpp_oset_dicts($key,$value) 1
  946. }
  947.  
  948. proc gen_oset_dicts {} {
  949.     global cpp_oset_dicts
  950.     if {![info exists cpp_oset_dicts]} {
  951.         return
  952.     }
  953.     set sect $ada_sections(h_incl_sect)
  954.     foreach keyval [lsort [array names cpp_oset_dicts]] {
  955.         set kv_list [split $keyval ,]
  956.         gen_oset_dict_type_def [lindex $kv_list 0] \
  957.                 [lindex $kv_list 1] $sect
  958.     }
  959.     unset cpp_oset_dicts
  960. }
  961.  
  962. # FuncMaps to be instantiated
  963. #
  964. global cpp_funcmaps
  965.  
  966. proc instantiate_funcmap {func} {
  967.     if $has_templates {
  968.         return
  969.     }
  970.     global cpp_funcmaps
  971.     set cpp_funcmaps($func) 1
  972. }
  973.  
  974. proc gen_funcmaps {} {
  975.     global cpp_funcmaps
  976.     if {![info exists cpp_funcmaps]} {
  977.         return
  978.     }
  979.     set sect $ada_sections(h_incl_sect)
  980.     foreach func [lsort [array names cpp_funcmaps]] {
  981.         gen_funcmap_type_def $func $sect
  982.     }
  983.     unset cpp_funcmaps
  984. }
  985.  
  986.     
  987. #
  988. # Return whether the given class is abstact, i.e. has any abstract operations.
  989. #
  990. proc is_abstract_class {class} {
  991.     foreach f [get_features $class] {
  992.         if {[get_obj_type $f] == "operation" && [is_abstract $f] == "1"} {
  993.             return 1
  994.         }
  995.     }
  996.     return 0
  997. }
  998.