home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1997 November
/
PCWorld_1997-11_cd.bin
/
software
/
programy
/
komix
/
DATA.Z
/
cpp_class.tcl
< prev
next >
Wrap
Text File
|
1997-03-19
|
24KB
|
874 lines
#---------------------------------------------------------------------------
#
# Copyright (c) 1993-1995 by Cadre Technologies Inc.
#
# This software is furnished under a license and may be used only in
# accordance with the terms of such license and with the inclusion of
# the above copyright notice. This software or any other copies thereof
# may not be provided or otherwise made available to any other person.
# No title to and ownership of the software is hereby transferred.
#
# The information in this software is subject to change without notice
# and should not be construed as a commitment by Cadre Technologies Inc.
#
#---------------------------------------------------------------------------
#
# File : @(#)cpp_class.tcl /main/hindenburg/8
# Author : frmo
# Original date : 4-2-1993
# Description : Class-level functions for C++ generation
#
#---------------------------------------------------------------------------
#
#
# Needed for E_FILE_OPEN_WRITE
#
require cgen_msg.tcl
global cpp_hdr_sections
set cpp_hdr_sections {
h_hdr_sect
h_incl_sect
h_fwd_decl_sect
h_enum_sect
h_class_nm_sect
h_friend_sect
h_ctor_sect
h_dtor_sect
h_pub_func_sect
h_pub_func_user-defined_sect
h_pub_func_attrib-access_sect
h_pub_func_assoc-access_sect
h_pub_data_sect
h_prot_func_sect
h_prot_func_user-defined_sect
h_prot_func_attrib-access_sect
h_prot_func_assoc-access_sect
h_priv_func_sect
h_priv_func_user-defined_sect
h_priv_func_attrib-access_sect
h_priv_func_assoc-access_sect
h_priv_data_user-defined_sect
h_priv_data_assoc-storage_sect
h_priv_data_sect
h_inl_sect
h_trailer_sect
}
global cpp_src_sections
set cpp_src_sections {
c_hdr_sect
c_incl_sect
c_static_sect
c_ctor_init_sect
c_ctor_init_iv_sect
c_ctor_body_sect
c_ctor_body_iv_sect
c_dtor_sect
c_impl_sect
c_impl_no_regen_sect
}
# for typedef and enum files
global limited_cpp_hdr_sections
set limited_cpp_hdr_sections {
h_hdr_sect
h_incl_sect
h_fwd_decl_sect
h_inl_sect
h_trailer_sect
}
# Global section array
#
global cpp_sections
# Determine the right section based on the accessibility specification and
# whether it is for reading or writing
#
proc get_hdr_sect {access {section_kind ""} {mode ""}} {
# Fixup for leaving out section_kind while still specifing mode
if {[lsearch {Public Protected Provate None} $section_kind] != -1} {
set mode $section_kind
set section_kind ""
}
if {$section_kind != ""} {
set section_kind "${section_kind}_"
}
case [split_access_mode $access $mode] in {
{Public} {
if [info exists cpp_sections(h_pub_func_${section_kind}sect)] {
return $cpp_sections(h_pub_func_${section_kind}sect)
} else {
return $cpp_sections(h_pub_func_sect)
}
}
{Protected} {
if [info exists cpp_sections(h_prot_func_${section_kind}sect)] {
return $cpp_sections(h_prot_func_${section_kind}sect)
} else {
return $cpp_sections(h_prot_func_sect)
}
}
{Private} {
if [info exists cpp_sections(h_priv_func_${section_kind}sect)] {
return $cpp_sections(h_priv_func_${section_kind}sect)
} else {
return $cpp_sections(h_priv_func_sect)
}
}
{None} {
return $cpp_sections(dev_null_sect)
}}
}
proc get_src_sect {access {is_inline 0} {mode ""}} {
if {[split_access_mode $access $mode] == "None"} {
return $cpp_sections(dev_null_sect)
}
if $is_inline {
return $cpp_sections(h_inl_sect)
}
return $cpp_sections(c_impl_no_regen_sect)
}
# Split up the access mode and return the right part of it
#
proc split_access_mode {access mode} {
if {$access == ""} {
return Public
}
set rw_ac_list [split $access -]
if {[llength $rw_ac_list] == 2} {
if {$mode == "r"} {
return [lindex $rw_ac_list 0]
}
return [lindex $rw_ac_list 1]
}
return $access
}
# Determine the section for an assoc accesser function based on
# the attribute "assoc_access"
#
proc get_assoc_hdr_sect {assoc {mode ""}} {
return [get_hdr_sect [$assoc getPropertyValue assoc_access] assoc-access $mode]
}
proc get_assoc_src_sect {assoc {is_inline 0} {mode ""}} {
return [get_src_sect [$assoc getPropertyValue assoc_access] $is_inline $mode]
}
# Determine the section for an attribute accesser function based on
# the attribute "attrib_access"
#
proc get_attrib_hdr_sect {attrib {mode ""}} {
return [get_hdr_sect [$attrib getPropertyValue attrib_access] attrib-access $mode]
}
proc get_attrib_src_sect {attrib {is_inline 0} {mode ""}} {
return [get_src_sect [$attrib getPropertyValue attrib_access] $is_inline $mode]
}
# Determine the type of a given section. "hdr" or "src" is returned.
# Special sections "hdr" and "src" are understood, and are returned as is.
#
proc determine_sect_type {sect} {
if {$sect == "src"} {
set type "src"
} elseif {$sect == "hdr"} {
set type "hdr"
} else {
global cpp_sections
foreach n [array names cpp_sections] {
if {$cpp_sections($n) == $sect} {
if {[lsearch $cpp_src_sections $n] != -1} {
set type "src"
} else {
set type "hdr"
}
break
}
}
}
return $type
}
# Create c++ sections
#
proc create_cpp_sections {sects} {
global cpp_sections
foreach sect $sects {
set cpp_sections($sect) [TextSection new]
$cpp_sections($sect) indent 0 "\t"
}
set cpp_sections(dev_null_sect) [TextSection new]
global ctor_init_sep ctor_init_iv_sep exists_ctor db_ctor_is_unique
set ctor_init_sep 1
set ctor_init_iv_sep 1
set exists_ctor 0
set db_ctor_is_unique 0
}
# give sections their initial contents
proc init_cpp_sections {class} {
set name [$class getName]
set is_db [is_db_class $class]
$cpp_sections(h_ctor_sect) append "public:\n"
$cpp_sections(h_ctor_sect) indent +
$cpp_sections(h_ctor_sect) append "// Default constructor/destructor\n"
$cpp_sections(h_dtor_sect) indent +
if {[$class specNodeSet] == ""} {
$cpp_sections(h_dtor_sect) append "~${name}();\n\n"
} else {
$cpp_sections(h_dtor_sect) append "virtual ~${name}();\n\n"
}
$cpp_sections(h_pub_func_sect) indent +
if {$is_db} { $cpp_sections(h_pub_func_sect) append "// Persistent storage methods\n" }
if [info exists cpp_sections(h_pub_func_user-defined_sect)] {
$cpp_sections(h_pub_func_user-defined_sect) indent +
$cpp_sections(h_pub_func_user-defined_sect) append "// User-defined methods\n"
}
if [info exists cpp_sections(h_pub_func_attrib-access_sect)] {
$cpp_sections(h_pub_func_attrib-access_sect) indent +
$cpp_sections(h_pub_func_attrib-access_sect) append "// Attribute accessor methods\n"
}
if [info exists cpp_sections(h_pub_func_assoc-access_sect)] {
$cpp_sections(h_pub_func_assoc-access_sect) indent +
$cpp_sections(h_pub_func_assoc-access_sect) append "// Association accessor methods\n"
}
$cpp_sections(h_pub_data_sect) indent +
if {$is_db} { $cpp_sections(h_pub_data_sect) append "// Persistent storage attributes\n" }
$cpp_sections(h_prot_func_sect) append "protected:\n"
$cpp_sections(h_prot_func_sect) indent +
if [info exists cpp_sections(h_prot_func_user-defined_sect)] {
$cpp_sections(h_prot_func_user-defined_sect) indent +
$cpp_sections(h_prot_func_user-defined_sect) append "// User-defined methods\n"
}
if [info exists cpp_sections(h_prot_func_attrib-access_sect)] {
$cpp_sections(h_prot_func_attrib-access_sect) indent +
$cpp_sections(h_prot_func_attrib-access_sect) append "// Attribute accessor methods\n"
}
if [info exists cpp_sections(h_prot_func_assoc-access_sect)] {
$cpp_sections(h_prot_func_assoc-access_sect) indent +
$cpp_sections(h_prot_func_assoc-access_sect) append "// Association accessor methods\n"
}
$cpp_sections(h_priv_func_sect) append "private:\n"
$cpp_sections(h_priv_func_sect) indent +
if [info exists cpp_sections(h_priv_func_user-defined_sect)] {
$cpp_sections(h_priv_func_user-defined_sect) indent +
$cpp_sections(h_priv_func_user-defined_sect) append "// User-defined methods\n"
}
if [info exists cpp_sections(h_priv_func_attrib-access_sect)] {
$cpp_sections(h_priv_func_attrib-access_sect) indent +
$cpp_sections(h_priv_func_attrib-access_sect) append "// Attribute accessor methods\n"
}
if [info exists cpp_sections(h_priv_func_assoc-access_sect)] {
$cpp_sections(h_priv_func_assoc-access_sect) indent +
$cpp_sections(h_priv_func_assoc-access_sect) append "// Association accessor methods\n"
}
if [info exists cpp_sections(h_priv_data_user-defined_sect)] {
$cpp_sections(h_priv_data_user-defined_sect) indent +
$cpp_sections(h_priv_data_user-defined_sect) append "// User-defined attributes\n"
}
if [info exists cpp_sections(h_priv_data_assoc-storage_sect)] {
$cpp_sections(h_priv_data_assoc-storage_sect) indent +
$cpp_sections(h_priv_data_assoc-storage_sect) append "// Association attribute storage\n"
}
$cpp_sections(h_priv_data_sect) indent +
$cpp_sections(c_ctor_body_sect) append "\n\{\n"
$cpp_sections(c_ctor_body_sect) indent +
$cpp_sections(c_ctor_body_iv_sect) indent +
$cpp_sections(c_dtor_sect) append "$name::~${name}()\n\{\n"
regen_unset "~$name" "()"
$cpp_sections(c_dtor_sect) indent +
$cpp_sections(c_impl_no_regen_sect) append "$REGEN_END\n\n"
}
# give sections their terminal contents
proc exit_cpp_sections {class} {
if [info exists cpp_sections(h_pub_func_user-defined_sect)] {
$cpp_sections(h_pub_func_user-defined_sect) append "\n"
}
if [info exists cpp_sections(h_pub_func_attrib-access_sect)] {
$cpp_sections(h_pub_func_attrib-access_sect) append "\n"
}
if [info exists cpp_sections(h_pub_func_assoc-access_sect)] {
$cpp_sections(h_pub_func_assoc-access_sect) append "\n"
}
if [info exists cpp_sections(h_prot_func_user-defined_sect)] {
$cpp_sections(h_prot_func_user-defined_sect) append "\n"
}
if [info exists cpp_sections(h_prot_func_attrib-access_sect)] {
$cpp_sections(h_prot_func_attrib-access_sect) append "\n"
}
if [info exists cpp_sections(h_prot_func_assoc-access_sect)] {
$cpp_sections(h_prot_func_assoc-access_sect) append "\n"
}
if [info exists cpp_sections(h_priv_func_user-defined_sect)] {
$cpp_sections(h_priv_func_user-defined_sect) append "\n"
}
if [info exists cpp_sections(h_priv_func_attrib-access_sect)] {
$cpp_sections(h_priv_func_attrib-access_sect) append "\n"
}
if [info exists cpp_sections(h_priv_func_assoc-access_sect)] {
$cpp_sections(h_priv_func_assoc-access_sect) append "\n"
}
if [info exists cpp_sections(h_priv_data_user-defined_sect)] {
$cpp_sections(h_priv_data_user-defined_sect) append "\n"
}
# SKIP THIS ONE: $cpp_sections(h_priv_data_assoc-storage_sect) append "\n"
$cpp_sections(h_priv_data_sect) indent -
$cpp_sections(h_priv_data_sect) append "\};\n\n"
set sect_iv $cpp_sections(c_ctor_init_iv_sect)
if {[$sect_iv contents] != ""} {
gen_ctor_sep $cpp_sections(c_ctor_init_sect)
}
$cpp_sections(c_ctor_body_iv_sect) indent -
$cpp_sections(c_ctor_body_iv_sect) append "\}\n\n"
$cpp_sections(c_dtor_sect) indent -
$cpp_sections(c_dtor_sect) append "\}\n\n"
if {[$cpp_sections(c_static_sect) contents] != ""} {
$cpp_sections(c_static_sect) append "\n"
}
}
# Write the sections to the right file and deallocate them
#
proc write_cpp_sections {class hsects csects} {
class2tgtfiles $class src_file h_file
set class_name [$class getName]
do_write_cpp_sections $class_name $h_file $hsects
do_write_cpp_sections $class_name $src_file $csects
unset cpp_sections(dev_null_sect)
}
proc do_write_cpp_sections {class_name file_name sects} {
global cpp_error_state
set did_save_file 0
if {[llength $sects] == 0 || $cpp_error_state} {
return $did_save_file
}
set nt $file_name
global skip_file
global gen_file
if {[info exists gen_file($nt)] ||
($import_new && ![info exists skip_file($nt)])} {
set cmp_sect [TextSection new]
foreach sect $sects {
set ctor_sect_mtch [string match c_ctor_* $sect]
if {$exists_ctor || ! $ctor_sect_mtch } {
$cmp_sect appendSect $cpp_sections($sect)
}
unset cpp_sections($sect)
}
if [section_equals_file $cmp_sect $nt] {
puts "$nt has not changed: file not written"
return 0
}
if {[M4CheckManager::getErrorCount] > 0} {
puts "Not saving $nt because of previous errors"
return 0
}
puts stdout "Creating $nt"
if {[catch {set fd [fstorage::open $nt w]} reason]} {
puts stderr $reason
m4_error $E_FILE_OPEN_WRITE $nt
} else {
if { [catch {fstorage::set_imp_from $nt $class_name} \
reason] } {
puts stderr $reason
}
$cmp_sect write $fd
fstorage::close $fd
set did_save_file 1
}
}
return $did_save_file
}
proc process_external_class_source {class} {
set class_name [$class getName]
set tmp_sect [TextSection new]
expand_text $tmp_sect [$class getPropertyValue class_source]
set files [string trim [$tmp_sect contents]]
set first 1
foreach entry [split $files ,] {
set entry [string trim $entry]
# first one is hplus_type
# all others are cplus_type
if $first {
set first 0
set ftype $hplus_type
} else {
set ftype $cplus_type
}
set file_name [class2file $class_name]
set nt ${file_name}.$ftype
global skip_file
global gen_file
if {[info exists gen_file($nt)] ||
($import_new && ![info exists skip_file($nt)])} {
set fullpath [find_file $entry]
if {$fullpath == ""} {
puts -nonewline "ERROR: class '[$class getName]': "
puts "external class source file '$entry' not found"
continue
}
puts "Importing external '$fullpath'"
puts "Creating $nt"
if {[catch {set out [fstorage::open $nt w]} reason]} {
puts stderr $reason
m4_error $E_FILE_OPEN_WRITE $nt
} else {
if { [catch {fstorage::set_imp_from $nt \
[$class getName]} reason] } {
puts stderr $reason
}
set max 8092
set in [open $fullpath r]
while {[set result [read $in $max]] != ""} {
puts -nonewline $out $result
}
close $in
fstorage::close $out
}
}
}
}
# find file using global 'exsrc_searchpath'
proc find_file {file} {
if [file exists $file] {
return $file
}
global exsrc_searchpath
if {! [info exists exsrc_searchpath]} {
return ""
}
set sep [searchPathSeparator]
foreach dir [split $exsrc_searchpath $sep] {
set fullpath [path_name concat $dir $file]
if [file exists $fullpath] {
return $fullpath
}
}
return ""
}
# read status arrays and generate 'only-once' code
proc gen_delayed_code {{class ""}} {
# default parameter: don't break old interface
gen_friends
gen_hdr_incs $class
gen_forwards
gen_src_incs $class
gen_sets
gen_osets
gen_dicts
gen_set_dicts
gen_oset_dicts
gen_funcmaps
global cpp_hdr_incs
catch {unset cpp_hdr_incs}
global cpp_hdr_files
catch {unset cpp_hdr_files}
}
# Global friend array
#
global cpp_friends
proc add_friend {friend} {
global cpp_friends
set cpp_friends([$friend getName]) 1
}
proc gen_friends {} {
global cpp_friends
if {![info exists cpp_friends]} {
return
}
set sect $cpp_sections(h_friend_sect)
$sect indent +
foreach class [lsort [array names cpp_friends]] {
$sect append "friend class $class;\n"
}
$sect indent +
unset cpp_friends
}
#
# forward declaration / class header inclusion management functions
#
# Global arrays to store the information
#
global cpp_forwards
global cpp_hdr_incs cpp_hdr_incs_name cpp_hdr_incs_name_ext
global cpp_src_incs cpp_src_incs_name cpp_src_incs_name_ext
proc add_forward {class} {
global cpp_forwards
set cpp_forwards([$class getName]) $class
}
proc add_forward_name {name} {
global cpp_forwards
set cpp_forwards($name) 1
}
proc add_hdr_inc {class} {
global cpp_hdr_incs
set cpp_hdr_incs([$class getName]) $class
}
proc add_hdr_inc_name {class_name {ext "hxx"}} {
global cpp_hdr_incs_name cpp_hdr_incs_name_ext
set cpp_hdr_incs_name($class_name) 1
set cpp_hdr_incs_name_ext($class_name) $ext
}
proc add_src_inc {class} {
global cpp_src_incs
set cpp_src_incs([$class getName]) $class
}
proc add_src_inc_name {class_name {ext "hxx"}} {
global cpp_src_incs_name cpp_src_incs_name_ext
set cpp_src_incs_name($class_name) 1
set cpp_src_incs_name_ext($class_name) $ext
}
# Generate forwards. If the class definition is also included, the forward
# is not generated.
#
proc gen_forwards {} {
global cpp_forwards cpp_hdr_incs
if {![info exists cpp_forwards]} {
return
}
set sect $cpp_sections(h_fwd_decl_sect)
foreach class [lsort [array names cpp_forwards]] {
if [info exists cpp_hdr_incs($class)] {
continue
}
$sect append "class $class;\n"
}
unset cpp_forwards
}
proc gen_hdr_incs {{cur_class ""}} {
# default parameter: don't break old interface
global cpp_hdr_incs cpp_hdr_incs_name cpp_hdr_incs_name_ext cpp_hdr_files
set gen_include_list ""
set user_include_list ""
if {$cur_class != ""} {
set cur_class_name [$cur_class getName]
} else {
set cur_class_name ""
}
if [info exists cpp_hdr_incs] {
foreach class [array names cpp_hdr_incs] {
if {$class == $cur_class_name} {
# don't include current header-file in itself
continue
}
set hdl $cpp_hdr_incs($class)
set incls [$hdl getPropertyValue include_list]
if {$incls == ""} {
lappend gen_include_list [$hdl getName]
set cpp_hdr_files([h_class2file $class]) 1
} else {
foreach incl [config_include_list [split $incls ,]] {
lappend user_include_list $incl
set cpp_hdr_files($incl) 1
}
}
}
}
if [info exists cpp_hdr_incs_name] {
foreach entry [array names cpp_hdr_incs_name] {
set file [h_class2file $entry $cpp_hdr_incs_name_ext($entry)]
if [info exists cpp_hdr_files($file)] {
continue
}
lappend gen_include_list $entry
set cpp_hdr_files($file) 1
}
}
foreach entry [lsort $gen_include_list] {
if {[info exists cpp_hdr_incs_name_ext($entry)]} {
set ext $cpp_hdr_incs_name_ext($entry)
} else {
set ext "hxx"
}
# prefer user includes
set idx [lsearch -exact $user_include_list [h_class2file $entry $ext]]
if {$idx == -1} {
gen_include $entry $cpp_sections(h_incl_sect) $ext
}
}
# do not sort ! remove duplicates
foreach entry $user_include_list {
if [info exists dup($entry)] {
continue;
}
set dup($entry) 1
gen_include_filename $entry $cpp_sections(h_incl_sect)
}
catch {unset cpp_hdr_incs_name}
catch {unset cpp_hdr_incs_name_ext}
}
# Generate includes for source file. Don't generate if the file is already
# included in the header file.
#
proc gen_src_incs {{cur_class ""}} {
# default parameter: don't break old interface
global cpp_src_incs cpp_src_incs_name cpp_src_incs_name_ext cpp_hdr_files
if {! [info exists cpp_sections(c_hdr_sect)]} {
catch {unset cpp_src_incs}
catch {unset cpp_src_incs_name}
catch {unset cpp_src_incs_name_ext}
return
}
if {$cur_class != ""} {
set cur_class_name [$cur_class getName]
} else {
set cur_class_name ""
}
set gen_include_list ""
set user_include_list ""
if [info exists cpp_src_incs] {
foreach class [array names cpp_src_incs] {
if {($class != $cur_class_name) && [info exists cpp_hdr_incs($class)]} {
continue
}
set hdl $cpp_src_incs($class)
set incls [$hdl getPropertyValue include_list]
if {$incls == ""} {
lappend gen_include_list [$hdl getName]
set src_files([h_class2file $class]) 1
} else {
foreach incl [config_include_list [split $incls ,]] {
if [info exists cpp_hdr_files($incl)] {
continue
}
lappend user_include_list $incl
set src_files($incl) 1
}
}
}
}
if [info exists cpp_src_incs_name] {
foreach entry [array names cpp_src_incs_name] {
set file [h_class2file $entry $cpp_src_incs_name_ext($entry)]
if [info exists cpp_hdr_files($file)] {
continue
}
if [info exists src_files($file)] {
continue
}
lappend gen_include_list $entry
}
}
foreach entry [lsort $gen_include_list] {
if {[info exists cpp_src_incs_name_ext($entry)]} {
set ext $cpp_src_incs_name_ext($entry)
} else {
set ext "hxx"
}
# prefer user includes
set idx [lsearch -exact $user_include_list [h_class2file $entry $ext]]
if {$idx == -1} {
gen_include $entry $cpp_sections(c_hdr_sect) $ext
}
}
# do not sort ! remove duplicates
foreach entry $user_include_list {
if [info exists dup($entry)] {
continue;
}
set dup($entry) 1
gen_include_filename $entry $cpp_sections(c_hdr_sect)
}
catch {unset cpp_src_incs}
catch {unset cpp_src_incs_name}
catch {unset cpp_src_incs_name_ext}
catch {unset src_files}
}
# Template emulation management
# Sets to be instantiated
#
global cpp_sets
proc instantiate_set {class} {
if $has_templates {
return
}
global cpp_sets
set cpp_sets($class) 1
}
proc gen_sets {} {
global cpp_sets
if {![info exists cpp_sets]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach class [lsort [array names cpp_sets]] {
gen_set_type_def $class $sect
}
unset cpp_sets
}
# Ordered Sets to be instantiated
#
global cpp_osets
proc instantiate_oset {class} {
if $has_templates {
return
}
global cpp_osets
set cpp_osets($class) 1
}
proc gen_osets {} {
global cpp_osets
if {![info exists cpp_osets]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach class [lsort [array names cpp_osets]] {
gen_oset_type_def $class $sect
}
unset cpp_osets
}
# Dicts to be instantiated
#
global cpp_dicts
proc instantiate_dict {key value} {
if $has_templates {
return
}
global cpp_dicts
set cpp_dicts($key,$value) 1
}
proc gen_dicts {} {
global cpp_dicts
if {![info exists cpp_dicts]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach keyval [lsort [array names cpp_dicts]] {
set kv_list [split $keyval ,]
gen_dict_type_def [lindex $kv_list 0] [lindex $kv_list 1] $sect
}
unset cpp_dicts
}
# Set Dicts to be instantiated
#
global cpp_set_dicts
proc instantiate_set_dict {key value} {
if $has_templates {
return
}
global cpp_set_dicts
set cpp_set_dicts($key,$value) 1
}
proc gen_set_dicts {} {
global cpp_set_dicts
if {![info exists cpp_set_dicts]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach keyval [lsort [array names cpp_set_dicts]] {
set kv_list [split $keyval ,]
gen_set_dict_type_def [lindex $kv_list 0] \
[lindex $kv_list 1] $sect
}
unset cpp_set_dicts
}
# Ordered Set Dicts to be instantiated
#
global cpp_oset_dicts
proc instantiate_oset_dict {key value} {
if $has_templates {
return
}
global cpp_oset_dicts
set cpp_oset_dicts($key,$value) 1
}
proc gen_oset_dicts {} {
global cpp_oset_dicts
if {![info exists cpp_oset_dicts]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach keyval [lsort [array names cpp_oset_dicts]] {
set kv_list [split $keyval ,]
gen_oset_dict_type_def [lindex $kv_list 0] \
[lindex $kv_list 1] $sect
}
unset cpp_oset_dicts
}
# FuncMaps to be instantiated
#
global cpp_funcmaps
proc instantiate_funcmap {func} {
if $has_templates {
return
}
global cpp_funcmaps
set cpp_funcmaps($func) 1
}
proc gen_funcmaps {} {
global cpp_funcmaps
if {![info exists cpp_funcmaps]} {
return
}
set sect $cpp_sections(h_incl_sect)
foreach func [lsort [array names cpp_funcmaps]] {
gen_funcmap_type_def $func $sect
}
unset cpp_funcmaps
}
#
# Return whether the given class is abstact, i.e. has any abstract operations.
#
proc is_abstract_class {class} {
foreach f [$class featureSet] {
if {[$f get_obj_type] == "operation" && [$f isAbstract] == "1"} {
return 1
}
}
return 0
}