home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1997 November
/
PCWorld_1997-11_cd.bin
/
software
/
programy
/
komix
/
DATA.Z
/
ne_funcs.tcl
< prev
next >
Wrap
Text File
|
1997-06-04
|
55KB
|
1,829 lines
#---------------------------------------------------------------------------
#
# Copyright (c) 1994-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 : @(#)ne_funcs.tcl /main/hindenburg/5
# Original date : 25-10-1994
# Description : NewEra generator functions
#
#---------------------------------------------------------------------------
#
proc oopl_model::generate {model} {
set selectedOoplClasses [getSelectedOoplClasses $model]
check_unique_file_names $selectedOoplClasses
foreach class $selectedOoplClasses {
if [$class isExternal] {
continue
}
if {[$class getName] == ""} {
puts stderr "Class without name skipped"
continue
}
class2tgtfiles $class nts nth
class2wiftgtfile $class ntw
global skip_file
global gen_file
global import_new
if [info exists gen_file($nth)] {
set gen_file($nts) 1
}
if {[$class getPropertyValue class_source] != "" &&
![is_gui_class $class] } {
process_external_class_source $class
continue
}
if {( $import_new &&
([is_special_class $class] ||
[info exists skip_file($nts)]) &&
[info exists skip_file($nth)] &&
([is_gui_class $class] || [info exists skip_file($ntw)]))
||
( !$import_new &&
![info exists gen_file($nts)] &&
![info exists gen_file($nth)] &&
![info exists gen_file($ntw)])} {
continue
}
global ne_error_state
set ne_error_state 0
generate $class
}
}
# Check uniqueness of filenames
#
proc check_unique_file_names {selectedOoplClasses} {
foreach class $selectedOoplClasses {
set cl_name [$class getName]
set file_name [class2file $cl_name]
if [$class isExternal] {
continue
}
if [info exists names($file_name)] {
error "Classes '$cl_name' and '$names($file_name)' map to the same file name" "" ERR_UNIQUE_FILENAME
}
set names($file_name) $cl_name
}
}
proc class::generate {class} {
if {[is_gui_class $class]} {
class::generate_wif $class
return
}
if [catch {prepare_regeneration $class} result] {
# something went wrong, find out what
switch $errorCode {
ERR_REGEN {puts stderr $result}
default {error $result $errorInfo $errorCode}
}
class2tgtfiles $class src_file h_file
global gen_file
catch {unset gen_file($src_file)}
if {! [info exists gen_file($h_file)]} {
return
}
}
create_ne_sections [concat $ne_hdr_sections $ne_src_sections]
init_ne_sections $class
puts stdout "Generating for class '[$class getName]'"
set obj_type [$class get_obj_type]
if {$obj_type == "class_generic_typedef" || $obj_type == "class_typedef"
} {
puts "WARNING: No constructor generated for this special class;\
add operation \$create to get the constructor generated"
}
class::gen_description $class $ne_sections(h_class_nm_sect)
set is_db [is_db_class $class]
if {$is_db} {
db_class_before $class
}
gen_user_added_include
add_src_inc $class
gen_class_decl $class
set sect $ne_sections(h_pub_func_sect)
foreach feat [$class featureSet] {
generate $feat $class
}
if {$is_db} {
db_class_after $class
}
gen_delayed_code
gen_user_added_ctor
gen_user_added_dtor
gen_user_added_source
append_obsolete_code $class
exit_ne_sections $class
write_ne_sections $class $ne_hdr_sections $ne_src_sections
}
proc class::gen_description {class sect} {
set ftext [$class getFreeText]
if {$ftext != ""} {
$sect append "\n"
string_to_oopl_comment $sect $ftext
$sect append "\n"
}
}
proc class_enum::generate {class} {
# No enum class in NewEra
puts "ERROR: NewEra does not support enumerations: no code \
generated for class '[$class getName]'"
global ne_error_state
set ne_error_state 1
}
proc class_enum::gen_class_decl {class} {
# No enum class in NewEra
}
proc class_typedef::generate {class} {
# No typedef class in NewEra
class::generate $class
}
proc class_typedef::gen_class_decl {class} {
# No typedef class in NewEra
class::gen_class_decl $class
}
proc class_generic_typedef::generate {class} {
# No generic typedef class in NewEra
class::generate $class
}
proc class_generic_typedef::gen_class_decl {class} {
# No generic typedef class in NewEra
class::gen_class_decl $class
}
# look in global 're_user_includes' for previous user includes
#
proc gen_user_added_include {} {
set sect $ne_sections(c_hdr_sect)
global re_user_includes
$sect append "$START_INCLUDE_MESSAGE\n"
$sect append $re_user_includes
$sect append "$END_INCLUDE_MESSAGE\n\n"
}
# look in global 're_ctor' for previous user additions to constructor
#
proc gen_user_added_ctor {} {
set sect $ne_sections(c_ctor_body_iv_sect)
global re_ctor
set old_ind [$sect indent]
$sect append "$START_CTOR_MESSAGE\n"
$sect indent 0
$sect append $re_ctor
$sect indent $old_ind
$sect append "$END_CTOR_MESSAGE\n"
}
# look in global 're_dtor' for previous user additions to destructor
#
proc gen_user_added_dtor {} {
set sect $ne_sections(c_dtor_sect)
global re_dtor
set old_ind [$sect indent]
$sect append "$START_DTOR_MESSAGE\n"
$sect indent 0
$sect append $re_dtor
$sect indent $old_ind
$sect append "$END_DTOR_MESSAGE\n"
}
#look in global 're_user_source' for previous user source code
#
proc gen_user_added_source {} {
global re_user_source
set sect $ne_sections(c_src_sect)
$sect append "$START_SOURCE_MESSAGE\n"
$sect append $re_user_source
$sect append "$END_SOURCE_MESSAGE\n\n"
}
proc class::gen_class_decl {class} {
set sect $ne_sections(h_class_nm_sect)
$sect append "CLASS [$class getName]"
set first 1
foreach super [$class genNodeSet] {
generate $super first
}
$sect append "\n"
}
proc link_class::generate {class} {
puts stdout "Generating for link class '[$class getName]'"
if {[$class getName] == ""} {
puts stderr "Link class without name skipped"
return
}
class::generate $class
}
proc link_class::gen_class_decl {class} {
class::gen_class_decl $class
}
proc inher_group::generate {group f} {
upvar $f first
set sect $ne_sections(h_class_nm_sect)
if {$first} {
$sect append " DERIVED FROM "
set first 0
} else {
# no MI in NewEra
puts "ERROR: NewEra does not support multiple inheritance:\
no code generated"
global ne_error_state
set ne_error_state 1
}
if {[$group isOverlapping] == "1"} {
puts "WARNING: Overlapping inheritance ignored; use normal\
inheritance instead"
}
add_hdr_inc [$group superClass]
$sect append "[$group getSuperClassName] "
}
proc feature::gen_description {feature sect} {
set ftext [$feature getFreeText]
if {$ftext != ""} {
string_to_oopl_comment $sect $ftext
}
}
proc data_attrib::generate {attrib class} {
if {[$attrib isClassFeature] == "1"} {
set shared_string "SHARED "
} else {
set shared_string ""
}
if {[[$attrib ooplType] get_obj_type] == "base_type"} {
set is_base_type 1
} else {
set is_base_type 0
}
set is_const_attrib [$attrib getPropertyValue is_const_attrib]
set is_constant [expr {$is_const_attrib == "1" && $is_base_type}]
set attrib_access [$attrib getPropertyValue attrib_access]
if {$is_constant} {
set shared_string ""
set constvar_string "CONSTANT"
set access_string \
[access2string [split_access_mode $attrib_access r]]
set sect $ne_sections(h_const_data_sect)
} else {
set constvar_string "VARIABLE"
set access_string "PRIVATE "
set sect $ne_sections(h_priv_data_sect)
}
if {$is_base_type} {
set copy_string ""
} else {
set copy_qualif [$attrib getPropertyValue copy_qualif]
set copy_string [copy_qualif2string $copy_qualif]
}
feature::gen_description $attrib $sect
set type_name [gen_var_decl [$attrib ooplType] [$attrib getName]]
$sect append "$access_string$shared_string$constvar_string\
$type_name $copy_string"
data_attrib_initial_value $attrib $class $is_constant
$sect append "\n"
if {$is_constant == "1"} {
return
}
set name [cap [$attrib getName]]
set type [generate [$attrib ooplType] fwd]
set sect [get_attrib_hdr_sect $attrib r]
set access_string [access2string [split_access_mode $attrib_access r]]
expand_text $sect {
~$access_string~${shared_string}FUNCTION get~${name}()\
RETURNING ~${type}
}
set sect [get_attrib_hdr_sect $attrib w]
set access_string [access2string [split_access_mode $attrib_access w]]
expand_text $sect {
~$access_string~${shared_string}FUNCTION\
set~${name}(new~${name} ~${type}) RETURNING VOID
}
set sect [get_attrib_src_sect $attrib r]
expand_text $sect {
FUNCTION ~[$class getName]::get~${name}() RETURNING ~${type}
RETURN ~[$attrib getName]
END FUNCTION
}
set sect [get_attrib_src_sect $attrib w]
expand_text $sect {
FUNCTION ~[$class getName]::set~${name}(new~${name} ~${type})\
RETURNING VOID
~[assign_var [$attrib getName] new${name} \
[$attrib ooplType]]
END FUNCTION
}
}
# generate an initial value line
proc data_attrib_initial_value {attrib class {is_constant 0}} {
if {[$attrib isClassFeature] == "1"} {
set is_shared 1
} else {
set is_shared 0
}
set iv [$attrib getPropertyValue initial_value]
set a_name [$attrib getName]
set c_name [$class getName]
if $is_constant {
set sect $ne_sections(h_const_data_sect)
if {$iv == ""} {
set iv "NULL"
}
$sect append " = $iv"
return
} elseif $is_shared {
set sect $ne_sections(c_static_sect)
set type [generate [$attrib ooplType] fwd]
$sect append "VARIABLE $c_name::$a_name $type"
if {$iv != ""} {
$sect append " = $iv"
} else {
gen_def_init_val $attrib $sect
}
$sect append "\n"
return
}
if {$iv == ""} {
return
}
set type [$attrib ooplType]
set sect $ne_sections(c_ctor_body_iv_sect)
$sect append "[assign_var $a_name $iv $type]\n"
}
# Returns the default initial value for $attrib
#
proc gen_def_init_val {attrib sect} {
if {[$attrib get_obj_type] != "qual_assoc_attrib"} {
return
}
set key [[$attrib qualifier] ooplType]
set value [$attrib ooplType]
if {[$attrib getMultiplicity] == "one"} {
set result [dict::initializer "" $key $value]
} else {
set setpfx [set_prefix $attrib]
set result [${setpfx}rsdict::initializer "" $key $value]
}
$sect append $result
}
# produces 'mem(value)' in ctor initializers section
proc append_ctor_init {mem value} {
set sect $ne_sections(c_ctor_init_sect)
gen_ctor_sep $sect
$sect append "${mem}($value)"
}
# produce correct separator for constructor initializer part
proc gen_ctor_sep {sect} {
global ctor_init_sep
if $ctor_init_sep {
set ctor_init_sep 0
$sect append " :\n"
} else {
$sect append ",\n"
}
}
# Common generate dispatch function for associations
#
proc gen_for_assoc {attrib class} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_data $attrib
${prefix}_get $attrib $class
${prefix}_set_self $attrib $class
${prefix}_rm_self $attrib $class
${prefix}_dtor $attrib $class
set type [$attrib ooplType]
add_src_inc $type
add_forward $type
}
# Common generate dispatch function for database associations
#
proc gen_for_db_assoc {attrib class} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_get $attrib $class
${prefix}_set $attrib $class
${prefix}_remove $attrib $class
set type [$attrib ooplType]
add_src_inc $type
add_forward $type
}
# Common generate dispatch function for links
#
proc gen_for_link {attrib class} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_data $attrib
${prefix}_get $attrib $class
set type [$attrib ooplType]
add_src_inc $type
add_forward $type
}
# Common generate dispatch function for reverse links
#
proc gen_for_rv_link {attrib class} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_data $attrib
${prefix}_get $attrib $class
${prefix}_dtor $attrib $class
set type [$attrib ooplType]
add_forward $type
}
# Dispatch functions for rm/set other
#
proc rm_other {attrib sect ptr} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_rm_other $attrib $sect $ptr
}
proc set_other {attrib decl_sect sect ptr} {
set prefix "[$attrib get_obj_type]::[$attrib getMultiplicity]"
${prefix}_set_other $attrib $decl_sect $sect $ptr
}
proc assoc_attrib::generate {attrib class} {
gen_for_assoc $attrib $class
}
proc assign_var {to from type_obj} {
return "LET $to = $from"
}
proc assoc_attrib::one_typedef {attrib class} {
puts "assoc_attrib::one_typedef CALLED"
}
proc assoc_attrib::one_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set type [[$attrib ooplType] getName]
set name [uncap [reference_name [$attrib getName]]]
$sect append "PUBLIC VARIABLE $name $type\n"
if [$attrib isMandatory] {
return
}
set sect $ne_sections(c_ctor_body_iv_sect)
$sect append "LET $name = NULL\n"
}
proc assoc_attrib::one_set_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION set${name}(new${name} $type)\
RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::set${name}(new${name} $type)\
RETURNING VOID\n"
$sect indent +
set opposite [$attrib opposite]
set ref_name [uncap [reference_name $name]]
set decl_sect [TextSection new]
set impl_sect [TextSection new]
$decl_sect indent 0 "\t"
$impl_sect indent 0 "\t"
if {$opposite != ""} {
$impl_sect append "IF $ref_name IS NOT NULL THEN\n"
$impl_sect indent +
rm_other $opposite $impl_sect $ref_name
$impl_sect indent -
$impl_sect append "END IF\n"
set_other $opposite $decl_sect $impl_sect new${name}
}
set decl_sect [removeDoubleLinesFromSection $decl_sect]
$sect appendSect $decl_sect
$sect appendSect $impl_sect
$sect append "LET $ref_name = new${name}\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc assoc_attrib::one_rm_self {attrib class} {
if [$attrib isMandatory] {
return
}
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION remove${name}()\
RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::remove${name}()\
RETURNING VOID\n"
$sect indent +
set opposite [$attrib opposite]
set ref_name [uncap [reference_name $name]]
if {$opposite != ""} {
$sect append "IF $ref_name IS NOT NULL THEN\n"
$sect indent +
rm_other $opposite $sect $ref_name
$sect indent -
$sect append "END IF\n"
}
$sect append "LET $ref_name = NULL\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc assoc_attrib::one_set_other {attrib decl_sect impl_sect ref} {
set name [$attrib getName]
set refname [uncap [reference_name $name]]
$impl_sect append "LET ${ref}.$refname = SELF\n"
}
proc assoc_attrib::one_rm_other {attrib sect ref} {
set name [$attrib getName]
set ref_name [uncap [reference_name $name]]
$sect append "LET ${ref}.$ref_name = NULL\n"
}
proc assoc_attrib::one_dtor {attrib class} {
set opposite [$attrib opposite]
if {$opposite != ""} {
set ref [uncap [reference_name [$attrib getName]]]
set sect $ne_sections(c_dtor_sect)
set decl_sect $ne_sections(c_dtor_decl_sect)
$sect append "IF $ref IS NOT NULL THEN\n"
$sect indent +
rm_other $opposite $sect $ref
$sect indent -
$sect append "END IF\n"
}
}
proc assoc_attrib::one_get {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}() RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}() RETURNING $type\n"
set ref_name [uncap [reference_name $name]]
$sect indent +
$sect append "RETURN $ref_name\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc assoc_attrib::many_typedef {attrib class} {
puts "assoc_attrib::many_typedef CALLED"
}
proc assoc_attrib::many_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [uncap [${setpfx}set_name [$attrib getName]]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_iv_sect)
$sect append "LET $name = NEW ${type}()\n"
}
proc assoc_attrib::many_set_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION add${name}(new${name} $type)\
RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::add${name}(new${name} $type)\
RETURNING VOID\n"
$sect indent +
set decl_sect [TextSection new]
set impl_sect [TextSection new]
$decl_sect indent 0 "\t"
$impl_sect indent 0 "\t"
set opposite [$attrib opposite]
set setpfx [set_prefix $attrib]
set set_name [uncap [${setpfx}set_name $name]]
set add_func [set ${setpfx}set::add]
set retval [set ${setpfx}set::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
$decl_sect append "VARIABLE $retvar $retval\n"
set ret_clause "RETURNING $retvar"
} else {
set ret_clause ""
}
$impl_sect append "CALL $set_name.${add_func}(new${name})\
$ret_clause\n"
if {$opposite != ""} {
set_other $opposite $decl_sect $impl_sect new${name}
}
set decl_sect [removeDoubleLinesFromSection $decl_sect]
$sect appendSect $decl_sect
$sect appendSect $impl_sect
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc assoc_attrib::many_rm_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION remove${name}(old${name} $type)\
RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::remove${name}(old${name}\
$type) RETURNING VOID\n"
$sect indent +
set opposite [$attrib opposite]
set setpfx [set_prefix $attrib]
set set_name [uncap [${setpfx}set_name $name]]
set remove_func [set ${setpfx}set::remove]
if [$attrib isMandatory] {
# mandatory aspect is compelled only by testing on size > 1
set size_func [set ${setpfx}set::size]
$sect append "IF $set_name.${size_func}() > 1 THEN\n"
$sect indent +
}
$sect append "CALL $set_name.${remove_func}(old${name})\n"
if {$opposite != ""} {
rm_other $opposite $sect old${name}
}
if [$attrib isMandatory] {
$sect indent -
$sect append "END IF\n"
}
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc assoc_attrib::many_set_other {attrib decl_sect impl_sect ref} {
set setpfx [set_prefix $attrib]
set name [uncap [${setpfx}set_name [$attrib getName]]]
set add_func [set ${setpfx}set::add]
set retval [set ${setpfx}set::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
set ret_clause "RETURNING $retvar"
$decl_sect append "VARIABLE $retvar $retval\n"
} else {
set ret_clause ""
}
$impl_sect append "CALL $ref.$name.${add_func}(SELF)\
$ret_clause\n"
}
proc assoc_attrib::many_rm_other {attrib sect ref} {
set setpfx [set_prefix $attrib]
set name [uncap [${setpfx}set_name [$attrib getName]]]
set remove_func [set ${setpfx}set::remove]
$sect append "CALL $ref.$name.${remove_func}(SELF)\n"
}
proc assoc_attrib::many_dtor {attrib class} {
set opposite [$attrib opposite]
if {$opposite != ""} {
set sect $ne_sections(c_dtor_sect)
set decl_sect $ne_sections(c_dtor_decl_sect)
set type [[$attrib ooplType] getName]
set name [$attrib getName]
set action "rm_other $opposite $sect"
set setpfx [set_prefix $attrib]
${setpfx}set::iter $decl_sect $sect $name $type $action
}
}
proc assoc_attrib::many_get {attrib class} {
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [cap [${setpfx}set_name [$attrib getName]]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}() RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}()\
RETURNING $type\n"
$sect indent +
$sect append "RETURN [uncap $name]\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc get_qualifier_type {assoc} {
return [generate [[$assoc qualifier] ooplType] fwd]
}
proc get_qualifier_name {assoc} {
return [[$assoc qualifier] getName]
}
proc qual_assoc_attrib::generate {attrib class} {
gen_for_assoc $attrib $class
}
proc qual_assoc_attrib::one_typedef {attrib class} {
puts "qual_assoc_attrib::one_typedef CALLED"
}
proc qual_assoc_attrib::one_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set type [dict_type_name [[$attrib qualifier] ooplType] \
[$attrib ooplType]]
set name [uncap [dict_name [$attrib getName]]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_sect)
set key [[$attrib qualifier] ooplType]
set value [$attrib ooplType]
set result [dict::initializer $name $key $value]
if {$result == ""} {
return
}
$sect append $result
}
proc qual_assoc_attrib::one_set_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION set${name}($key $q_type,\
new${name} $type) RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::set${name}($key $q_type,\
new${name} $type) RETURNING VOID\n"
$sect indent +
set decl_sect [TextSection new]
set impl_sect [TextSection new]
$decl_sect indent 0 "\t"
$impl_sect indent 0 "\t"
set opposite [$attrib opposite]
set dct_name [uncap [dict_name $name]]
if {$opposite != ""} {
set action "rm_other $opposite $decl_sect $impl_sect"
dict::get_test_and_act $impl_sect $name $key $type $action
set_other $opposite $decl_sect $impl_sect new${name}
}
set decl_sect [removeDoubleLinesFromSection $decl_sect]
$sect appendSect $decl_sect
$sect appendSect $impl_sect
$sect append "CALL $dct_name.${dict::set}($key, new${name})\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_assoc_attrib::one_rm_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION remove${name}($key $q_type)\
RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::remove${name}($key $q_type)\
RETURNING VOID\n"
$sect indent +
set opposite [$attrib opposite]
set dct_name [uncap [dict_name $name]]
if {$opposite != ""} {
set action "rm_other $opposite $sect"
dict::get_test_and_act $sect $name $key $type $action
}
$sect append "CALL $dct_name.${dict::remove}($key)\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_assoc_attrib::one_set_other {attrib decl_sect impl_sect ref} {
set name [uncap [dict_name [$attrib getName]]]
$impl_sect append \
"CALL $ref.$name.${dict::set}(\{ supply key here \}, SELF)\n"
}
proc qual_assoc_attrib::one_rm_other {attrib sect ref} {
set name [uncap [dict_name [$attrib getName]]]
$sect append \
"CALL $ref.$name.${dict::remove}(\{ supply key here \})\n"
}
proc qual_assoc_attrib::one_dtor {attrib class} {
set opposite [$attrib opposite]
if {$opposite != ""} {
set sect $ne_sections(c_dtor_sect)
set decl_sect $ne_sections(c_dtor_decl_sect)
set type [[$attrib ooplType] getName]
set qual_type [[[$attrib qualifier] ooplType] getName]
set name [$attrib getName]
set action "rm_other $opposite $sect"
dict::iter $decl_sect $sect $name $type $qual_type $action
}
}
proc qual_assoc_attrib::one_get {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}($key $q_type)\
RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}($key $q_type)\
RETURNING $type\n"
set dct_name [uncap [dict_name $name]]
$sect indent +
dict::get_and_return $sect $dct_name $key $type
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_assoc_attrib::many_typedef {attrib class} {
puts "qual_assoc_attrib::many_typedef CALLED"
}
proc qual_assoc_attrib::many_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set setpfx [set_prefix $attrib]
set type [${setpfx}set_dict_type_name \
[[$attrib qualifier] ooplType] [$attrib ooplType]]
set name [uncap [${setpfx}set_dict_name [$attrib getName]]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_sect)
set key [[$attrib qualifier] ooplType]
set value [$attrib ooplType]
set result [${setpfx}rsdict::initializer $name $key $value]
if {$result == ""} {
return
}
$sect append $result
}
proc qual_assoc_attrib::many_set_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION add${name}($key $q_type,\
new${name} $type) RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::add${name}($key $q_type,\
new${name} $type) RETURNING VOID\n"
$sect indent +
set decl_sect [TextSection new]
set impl_sect [TextSection new]
$decl_sect indent 0 "\t"
$impl_sect indent 0 "\t"
set setpfx [set_prefix $attrib]
set sdct_name [uncap [${setpfx}set_dict_name [$attrib getName]]]
set add_func [set ${setpfx}rsdict::add]
set retval [set ${setpfx}rsdict::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
$decl_sect append "VARIABLE $retvar $retval\n"
set ret_clause "RETURNING $retvar"
} else {
set ret_clause ""
}
$impl_sect append "CALL $sdct_name.${add_func}($key,\
new${name}) $ret_clause\n"
set opposite [$attrib opposite]
if {$opposite != ""} {
set_other $opposite $decl_sect $impl_sect new${name}
}
set decl_sect [removeDoubleLinesFromSection $decl_sect]
$sect appendSect $decl_sect
$sect appendSect $impl_sect
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_assoc_attrib::many_rm_self {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set cl_name [$class getName]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set sect [get_assoc_hdr_sect $attrib w]
set access [get_access_mode [$attrib getPropertyValue assoc_access] w]
$sect append "${access}FUNCTION remove${name}($key $q_type,\
old${name} $type) RETURNING VOID\n"
set sect [get_assoc_src_sect $attrib w]
$sect append "FUNCTION $cl_name::remove${name}($key $q_type,\
old${name} $type) RETURNING VOID\n"
$sect indent +
set opposite [$attrib opposite]
if {$opposite != ""} {
rm_other $opposite $sect old${name}
}
set setpfx [set_prefix $attrib]
set sdct_name [uncap [${setpfx}set_dict_name [$attrib getName]]]
set remove_func [set ${setpfx}rsdict::remove]
$sect append \
"CALL $sdct_name.${remove_func}($key, old${name})\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_assoc_attrib::many_set_other {attrib decl_sect impl_sect ref} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set setpfx [set_prefix $attrib]
set sdct_name [uncap [${setpfx}set_dict_name $name]]
set add_func [set ${setpfx}rsdict::add]
set retval [set ${setpfx}rsdict::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
set ret_clause "RETURNING $retvar"
$decl_sect append "VARIABLE $retvar $retval\n"
} else {
set ret_clause ""
}
$impl_sect append "CALL $ref.$sdct_name.${add_func}(\
\{ supply key here \}, SELF) $ret_clause\n"
}
proc qual_assoc_attrib::many_rm_other {attrib sect ref} {
set type [[$attrib ooplType] getName]
set name [cap [$attrib getName]]
set setpfx [set_prefix $attrib]
set sdct_name [uncap [${setpfx}set_dict_name $name]]
set remove_func [set ${setpfx}rsdict::remove]
$sect append "CALL $ref.$sdct_name.${remove_func}(\
\{ supply key here \}, SELF)\n"
}
proc qual_assoc_attrib::many_dtor {attrib class} {
set opposite [$attrib opposite]
if {$opposite != ""} {
set sect $ne_sections(c_dtor_sect)
set decl_sect $ne_sections(c_dtor_decl_sect)
set type [$attrib ooplType]
set q_type [string trimright [generate [[$attrib qualifier] \
ooplType] inc]]
set name [cap [$attrib getName]]
set action "rm_other $opposite $sect"
set setpfx [set_prefix $attrib]
${setpfx}rsdict::iter $decl_sect $sect $name $type $q_type $action
}
}
proc qual_assoc_attrib::many_get {attrib class} {
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [cap [$attrib getName]]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}($key $q_type)\
RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}($key $q_type)\
RETURNING $type\n"
set sdct_name [uncap [${setpfx}set_dict_name $name]]
$sect indent +
${setpfx}rsdict::get_and_return $sect $name $key $type
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc operation::generate {oper class} {
global ne_error_state
set name [$oper getName]
set is_ctor [expr {$name == "create" && [$oper isClassFeature]== "1"}]
if {$is_ctor && [is_db_class $class]} {
puts "ERROR: constructor function \$create not allowed in database class '$name'"
set ne_error_state 1
return
}
set h_sect [get_hdr_sect [$oper getPropertyValue method_access]]
feature::gen_description $oper $h_sect
set c_sect $ne_sections(c_impl_sect)
set is_abstract [expr {[$oper isAbstract] == "1"}]
if $is_ctor {
set type ""
set name [$class getName]
} else {
set type [generate [$oper ooplType] fwd]
}
set method_access [$oper getPropertyValue method_access]
if {$is_ctor && $is_abstract && $method_access == "Public"} {
set access [access2string "Protected"]
} else {
set access [get_access_mode $method_access]
}
set is_shared [expr {[$oper isClassFeature] == "1"} && !$is_ctor]
$h_sect append "$access"
if $is_shared {
$h_sect append "SHARED "
}
if {[$oper getPropertyValue is_event] == "1"} {
$h_sect append "EVENT "
} else {
$h_sect append "FUNCTION "
}
$h_sect append "${name}("
set first 1
foreach param [$oper parameterSet] {
set default [$param getPropertyValue default_value]
set decl fwd
if {$default != ""} {
set decl inc
}
generate $param $h_sect first $decl
if {$default != ""} {
$h_sect append " : $default"
}
}
$h_sect append ")"
if {$type != ""} {
$h_sect append " RETURNING $type"
}
$h_sect append "\n"
if {[$oper getPropertyValue is_event] == "1"} {
return
}
set tmp_c_sect [TextSection new]
$c_sect append "FUNCTION [$class getName]::${name}"
$tmp_c_sect append "("
set first 1
foreach param [$oper parameterSet] {
generate $param $tmp_c_sect first fwd
}
$tmp_c_sect append ")"
set method_type [$tmp_c_sect contents]
if {$type != ""} {
$tmp_c_sect append " RETURNING $type"
}
$c_sect appendSect $tmp_c_sect
set impl_proc [string trim [$oper getPropertyValue method_impl]]
if {$impl_proc == ""} {
# get previously prepared body
get_method_body $name $method_type $c_sect
$c_sect append "END FUNCTION\n\n"
} else {
set impl_proc operation::$impl_proc
if {[info procs $impl_proc] != ""} {
$c_sect append "\n"
$c_sect indent +
$c_sect append [$impl_proc $oper $class $c_sect]
$c_sect indent -
$c_sect append "END FUNCTION\n\n"
regen_unset $name $method_type
} else {
puts stderr "WARNING: Tcl procedure " nonewline
puts stderr "'$impl_proc' not found"
# fall back to regeneration
get_method_body $name $method_type $c_sect
$c_sect append "END FUNCTION\n\n"
}
}
}
proc parameter::generate {param sect f decl {is_db 0} {with_types 1}} {
upvar $f first
if $first {
set first 0
} else {
$sect append ", "
}
if !$with_types {
$sect append "[$param getName]"
return
}
set type_str [generate [$param ooplType] $decl]
if {$is_db && [[$param ooplType] get_obj_type] == "base_type"} {
set type_str [map_fgl2ixval $type_str]
}
$sect append \
"[$param getName] $type_str"
}
proc base_type::generate {type decl} {
set result [$type getType3GL]
if [regexp {(VAR)?CHAR\([0-9][0-9]*\)} $result] {
regsub {\([0-9][0-9]*\)} $result "\(*\)" result
}
return $result
}
proc base_type::gen_var_decl {type name} {
set type [$type getType3GL]
return "$name $type"
}
proc class_type::generate {type decl} {
set name [$type getName]
if {$name == ""} {
return "VOID"
}
if {$decl == "fwd"} {
add_forward $type
add_src_inc $type
} else {
add_hdr_inc $type
}
return $name
}
proc class_type::gen_var_decl {type name} {
add_forward $type
return "$name [$type getName]"
}
proc typedef_type::generate {type decl} {
return [class_type::generate $type $decl]
}
proc typedef_type::gen_var_decl {type name} {
return [class_type::gen_var_decl $type $name]
}
proc enum_type::generate {type decl} {
return [class_type::generate $type $decl]
}
proc enum_type::gen_var_decl {type name} {
return [class_type::gen_var_decl $type $name]
}
proc generic_typedef_type::generate {type decl} {
return [class_type::generate $type $decl]
}
proc generic_typedef_type::gen_var_decl {type name} {
return [class_type::gen_var_decl $type $name]
}
proc copy_qualif2string {copy_qualif} {
case $copy_qualif in {
{Shallow ""} {return ""}
{Null} {return "NULL COPY "}
{Deep} {return "DEEP COPY "}
}
}
proc access2string {access} {
case $access in {
{Public ""} {return "PUBLIC "}
{Protected} {return "PROTECTED "}
{Private} {return "PRIVATE "}
}
}
proc get_access_mode {access {mode ""}} {
return [access2string [split_access_mode $access $mode]]
}
# Determine if all initializers for a class refer to a part of the key
# This is done by comparing the signature of all keys with that of all
# creation parameters
#
proc all_inits_are_keys {class} {
set ctor_list ""
foreach ct_param [$class creationParamSet] {
lappend ctor_list [[$ct_param ooplType] getType3GL]
}
set key_list ""
foreach key [get_col_list [$class table] KEYS] {
if {[$key getUniqueName] != $TYPE_ID_NM} {
lappend key_list [$key getType3GL]
}
}
return [expr {$ctor_list == $key_list}]
}
# test if a operation signature equals the
# database-runtime-constructor
#
proc is_eq_db_ctor {oper class} {
set is_db [is_db_class $class]
# easy tests first
if {! $is_db || [$oper getName] != "create"} {
return 0
}
if {[$oper get_obj_type] == "constructor"} {
set params [$class creationParamSet]
} else {
set params [$oper parameterSet]
}
set keys [get_col_list [$class table] KEYS]
# number of parameters must be equal
# correct for extra key
set lp [llength $params]
incr lp
if {$lp != [llength $keys]} {
return 0
}
foreach param $params {
set key [lvarpop keys]
if {[$key getUniqueName] == $TYPE_ID_NM} {
set key [lvarpop keys]
}
set key_t [string trim [$key getType3GL]]
if [regexp {(VAR)?CHAR\([0-9][0-9]*\)} $key_t] {
regsub {\([0-9][0-9]*\)} $key_t "\(*\)" key_t
}
set par_t [string trim [generate [$param ooplType] fwd]]
if {$key_t != $par_t} {
return 0
}
# OK, continue
}
return 1
}
proc constructor::generate {ctor class} {
global exists_ctor
set exists_ctor 1
set is_db [is_db_class $class]
if $is_db {
db_constructor::generate $ctor $class
return
}
set class_nm [$class getName]
set ctor_nm $class_nm
set sect $ne_sections(h_ctor_sect)
$sect append "FUNCTION "
set with_default 1
gen_ctor_decl $class $sect $ctor_nm $with_default
$sect append "\n"
set sect $ne_sections(c_ctor_init_sect)
$sect append "FUNCTION $class_nm::"
set with_default 0
gen_ctor_decl $class $sect $ctor_nm $with_default
# $sect append "\n"
$sect indent +
set decl_sect $ne_sections(c_ctor_decl_sect)
set body $ne_sections(c_ctor_body_sect)
foreach init [$ctor initializerSet] {
generate $init $sect $decl_sect $body $class
}
}
proc gen_ctor_decl {class sect ctor_nm with_default} {
$sect append "${ctor_nm}"
set tmp_sect [TextSection new]
$tmp_sect append "("
set first 1
foreach param [$class creationParamSet] {
set default ""
set decl fwd
if {$with_default} {
set default [$param getPropertyValue default_value]
if {$default != ""} {
set decl inc
}
}
parameter::generate $param $tmp_sect first $decl
if {$default != ""} {
$tmp_sect append " : $default"
}
}
$tmp_sect append ")"
$sect appendSect $tmp_sect
set method_type [$tmp_sect contents]
### quick hack
global re_found_ctor
if {$with_default && $re_found_ctor} {
regen_unset $ctor_nm $method_type
}
}
proc attrib_init::generate {init init_sect decl_sect body_sect class} {
set attrib [$init attrib]
if {[$attrib get_obj_type] == "db_data_attrib"} {
set class_data [uncap [$class getName]]Data
set col [$attrib column]
set col_nr [get_column_nr $col]
$body_sect append "LET retVal =\
$class_data.setVal(COPY [$init getName], $col_nr)\n"
} else {
$body_sect append \
"LET [$attrib getName] = [$init getName]\n"
}
}
proc assoc_init::generate {init init_sect decl_sect body_sect class} {
gen_initializer [$init assoc] $init $decl_sect $body_sect $class
}
proc qual_init::generate {init init_sect decl_sect body_sect class} {
set qual [$init qualifier]
if {[$qual get_obj_type] == "db_qualifier"} {
set class_data [uncap [$class getName]]Data
set col [$qual column]
set col_nr [get_column_nr $col]
$body_sect append "LET retVal =\
$class_data.setVal(COPY [$init getName], $col_nr)\n"
}
# non-db qualifier does not need initialization
}
proc sc_init::generate {init init_sect decl_sect body_sect class} {
set nm_list ""
foreach param [$init parameterSet] {
lappend nm_list [$param getName]
}
set superClass [$init ooplClass]
if {[$superClass get_obj_type] == "class"} {
gen_ctor_sep $init_sect
$init_sect append \
"[$superClass getName]([join $nm_list ", "])"
} else {
# Here: [$superClass get_obj_type] == "db_class"
expand_text $init_sect {
IF init~[cap [$superClass getName]](~[\
join $nm_list ", "]) < 0 THEN
RETURN -1
END IF
}
}
}
proc inher_key_init::generate {init init_sect decl_sect body_sect class} {
set col [$init key]
set name [$col getUniqueName]
if {$name == $TYPE_ID_NM} {
return
}
set col_nr [get_column_nr $col]
set fcolnr [get_foreign_column_nr $col]
set class_nm [[$init ooplClass] getName]
set super_data [uncap $class_nm]Data
set class_data [uncap [$class getName]]Data
$body_sect append "LET retVal = $class_data.setVal(COPY\
$super_data.getVal($fcolnr), $col_nr)\n"
}
# Generate code to call func for all bases
#
proc call_for_all_bases {class sect func} {
set supers [$class genNodeSet]
if [lempty $supers] {
return
}
$sect append "\n"
$sect indent +
foreach super $supers {
set name [$super getSuperClassName]
expand_text $sect {
IF ~$name::~${func}() < 0 THEN
RETURN -1
END IF
}
}
$sect indent -
}
proc get_root_class {class} {
set supers [$class genNodeSet]
if [lempty $supers] {
return $class
}
return [get_root_class [[lindex $supers 0] superClass]]
}
proc rv_link_attrib::generate {attrib class} {
# multiplicity should always be 'one' here
gen_for_rv_link $attrib $class
}
proc rv_link_attrib::one_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set type [[$attrib ooplType] getName]
set name [reference_name [$attrib getName]]
$sect append "PUBLIC VARIABLE $name $type\n"
}
proc rv_link_attrib::one_get {attrib class} {
set type [[$attrib ooplType] getName]
set name [$attrib getName]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get[cap $name]()\
RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get[cap $name]()\
RETURNING $type\n"
set ref_name [reference_name $name]
$sect indent +
$sect append "RETURN $ref_name\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc rv_link_attrib::one_dtor {attrib class} {
set opposite [$attrib opposite]
if {$opposite != ""} {
set ref [reference_name [$attrib getName]]
set sect $ne_sections(c_dtor_sect)
set decl_sect $ne_sections(c_dtor_decl_sect)
rm_other $opposite $sect $ref
}
}
proc qual_link_attrib::generate {attrib class} {
gen_for_link $attrib $class
}
proc qual_link_attrib::one_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set type [dict_type_name [[$attrib qualifier] ooplType] \
[$attrib ooplType]]
set name [uncap [dict_name \
"[[$attrib ooplType] getName]Of[cap [$attrib getName]]"]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_sect)
set key [[$attrib qualifier] ooplType]
set value [$attrib ooplType]
set result [dict::initializer $name $key $value]
if {$result == ""} {
return
}
$sect append $result
}
proc qual_link_attrib::one_rm_other {attrib sect ref} {
set name [uncap [dict_name \
[[$attrib ooplType] getName]Of[cap [$attrib getName]]]]
$sect append "CALL $ref.$name.${dict::remove}(\
\{ supply key here \})\n"
}
proc qual_link_attrib::one_set_other {attrib decl_sect impl_sect ref} {
set name [uncap [dict_name \
[[$attrib ooplType] getName]Of[cap [$attrib getName]]]]
set qual [[$attrib qualifier] getName]
$impl_sect append "CALL $ref.$name.${dict::set}($qual, SELF)\n"
}
proc qual_link_attrib::one_get {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap [[$attrib ooplType] getName]Of[cap [$attrib getName]]]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}($key $q_type)\
RETURNING $type\n"
set sect [get_assoc_src_sect $attrib r]
$sect append "FUNCTION $cl_name::get${name}($key $q_type)\
RETURNING $type\n"
set dct_name [uncap [dict_name $name]]
$sect indent +
dict::get_and_return $sect $dct_name $key $type
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_link_attrib::many_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set setpfx [set_prefix $attrib]
set type [${setpfx}set_dict_type_name \
[[$attrib qualifier] ooplType] [$attrib ooplType]]
set name [uncap [${setpfx}set_dict_name \
[[$attrib ooplType] getName]Of[cap [$attrib getName]]]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_sect)
set key [[$attrib qualifier] ooplType]
set value [$attrib ooplType]
set result [${setpfx}rsdict::initializer $name $key $value]
if {$result == ""} {
return
}
$sect append $result
}
proc qual_link_attrib::many_get {attrib class} {
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [cap [[$attrib ooplType] getName]Of[cap [$attrib getName]]]
set key [get_qualifier_name $attrib]
set q_type [get_qualifier_type $attrib]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}($key $q_type)\
RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}($key $q_type)\
RETURNING $type\n"
$sect indent +
${setpfx}rsdict::get_and_return $sect $name $key $type
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc qual_link_attrib::many_set_other {attrib decl_sect impl_sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set qual [[$attrib qualifier] getName]
set setpfx [set_prefix $attrib]
set s_name [uncap [${setpfx}set_dict_name $name]]
set add_func [set ${setpfx}rsdict::add]
set retval [set ${setpfx}rsdict::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
set ret_clause "RETURNING $retvar"
$decl_sect append "VARIABLE $retvar $retval\n"
} else {
set ret_clause ""
}
$impl_sect append "CALL $ref.$s_name.${add_func}($qual, SELF)\
$ret_clause\n"
}
proc qual_link_attrib::many_rm_other {attrib sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set setpfx [set_prefix $attrib]
set s_name [uncap [${setpfx}set_dict_name $name]]
set remove_func [set ${setpfx}rsdict::remove]
$sect append "CALL $ref.$s_name.${remove_func}(\
\{ supply key here \}, SELF)\n"
}
proc link_attrib::generate {attrib class} {
gen_for_link $attrib $class
}
proc link_attrib::one_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set type [[$attrib ooplType] getName]
set name [uncap [reference_name "${type}Of[cap [$attrib getName]]"]]
$sect append "PUBLIC VARIABLE $name $type\n"
}
proc link_attrib::one_get {attrib class} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}() RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}() RETURNING $type\n"
set ref_name [uncap [reference_name $name]]
$sect indent +
$sect append "RETURN $ref_name\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc link_attrib::one_rm_other {attrib sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set ref_name [uncap [reference_name $name]]
$sect append "LET $ref.$ref_name = NULL\n"
}
proc link_attrib::one_set_other {attrib decl_sect impl_sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set ref_name [uncap [reference_name $name]]
$impl_sect append "LET $ref.$ref_name = SELF\n"
}
proc link_attrib::many_data {attrib} {
set sect $ne_sections(h_pub_data_sect)
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [uncap [${setpfx}set_name "[[$attrib ooplType] getName]Of[cap [$attrib getName]]"]]
$sect append "PUBLIC VARIABLE $name $type\n"
set sect $ne_sections(c_ctor_body_iv_sect)
$sect append "LET $name = NEW ${type}()\n"
}
proc link_attrib::many_get {attrib class} {
set setpfx [set_prefix $attrib]
set type [${setpfx}set_type_name [$attrib ooplType]]
set name [cap [${setpfx}set_name "[[$attrib ooplType] getName]Of[cap [$attrib getName]]"]]
set cl_name [$class getName]
set sect [get_assoc_hdr_sect $attrib r]
set access [get_access_mode [$attrib getPropertyValue assoc_access] r]
$sect append "${access}FUNCTION get${name}() RETURNING $type\n"
set sect $ne_sections(c_impl_no_regen_sect)
$sect append "FUNCTION $cl_name::get${name}() RETURNING $type\n"
$sect indent +
$sect append "RETURN [uncap $name]\n"
$sect indent -
$sect append "END FUNCTION\n\n"
}
proc link_attrib::many_set_other {attrib decl_sect impl_sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set setpfx [set_prefix $attrib]
set s_name [uncap [${setpfx}set_name $name]]
set add_func [set ${setpfx}set::add]
set retval [set ${setpfx}set::add_retval]
set retvar ${add_func}RetVal
if {$retval != "VOID"} {
set ret_clause "RETURNING $retvar"
$decl_sect append "VARIABLE $retvar $retval\n"
} else {
set ret_clause ""
}
$impl_sect append "CALL $ref.$s_name.${add_func}(SELF)\
$ret_clause\n"
}
proc link_attrib::many_rm_other {attrib sect ref} {
set type [[$attrib ooplType] getName]
set name [cap "${type}Of[cap [$attrib getName]]"]
set setpfx [set_prefix $attrib]
set s_name [uncap [${setpfx}set_name $name]]
set remove_func [set ${setpfx}set::remove]
$sect append "CALL $ref.$s_name.${remove_func}(SELF)\n"
}
proc assoc_attrib::gen_initializer {attrib init decl_s body_s class} {
set refname [uncap [reference_name [$attrib getName]]]
$body_s append "LET $refname = [$attrib getName]\n"
set opposite [$attrib opposite]
if {$opposite != ""} {
set_other $opposite $decl_s $body_s $refname
}
}
proc rv_link_attrib::gen_initializer {attrib init decl_s body_s class} {
set refname [uncap [reference_name [$attrib getName]]]
$body_s append "LET $refname = [$init getName]\n"
set opposite [$attrib opposite]
if {$opposite != ""} {
set_other $opposite $decl_s $body_s $refname
add_src_inc [$attrib ooplType]
}
}
# Generate a NewEra parameter declaration
#
proc gen_param_decl_ne {section object selector decl {separator ", "}
{newline ""}} {
set columns [get_col_list $object $selector]
if [lempty $columns] {
return
}
set col [lvarpop columns]
$section pushIndent
set t_par [base_type::generate $col fwd]
set t_par_ixval [map_fgl2ixval ${t_par}]
if {$decl == "fwd"} {
add_forward_name $t_par_ixval
add_src_sys_inc_name [ixval2hdr $t_par_ixval]
} else {
add_hdr_sys_inc_name [ixval2hdr $t_par_ixval]
}
$section append \
"[$col getUniqueName] $t_par_ixval"
set newpf $separator$newline
foreach col $columns {
set t_par [base_type::generate $col fwd]
set t_par_ixval [map_fgl2ixval ${t_par}]
if {$decl == "fwd"} {
add_forward_name $t_par_ixval
add_src_sys_inc_name [ixval2hdr $t_par_ixval]
} else {
add_hdr_sys_inc_name [ixval2hdr $t_par_ixval]
}
$section append \
"$newpf[$col getUniqueName] $t_par_ixval"
}
$section popIndent
$section append $newline
}
# Generate a check for the nullability of the columns of a link. These columns
# are either ALL null or ALL not null, so it suffices to check only the
# first column.
#
proc gen_null_check {sect link row_name {ret_val 0} {valvar val} } {
set col [lindex [$link columnSet] 0]
if {$ret_val == ""} {
set space ""
} else {
set space " "
}
expand_text $sect {
LET ~$valvar = ~${row_name}.getVal(~[get_column_nr $col])
IF ~$valvar IS NULL THEN
RETURN~${space}~$ret_val
END IF
IF ~$valvar.isNull() THEN
RETURN~${space}~$ret_val
END IF
}
}
proc is_db_class {class} {
return [string match {db_*} [$class get_obj_type]]
}
proc class2tgtfiles {class src inc} {
upvar $src src_f
upvar $inc inc_f
set class_name [class2file [$class getName]]
set src_f $class_name.$fourgl_type
set inc_f $class_name.$fourgh_type
}
proc class2wiftgtfile {class wif} {
upvar $wif wif_f
set wif_name [class2file [$class getName]]
set wif_f $wif_name.$wif_tmpl_type
}
# we want 'class_typedef'
# or 'class_enum'
# or 'class_generic_typedef'
proc is_special_class {class} {
return [string match {*class_*} [$class get_obj_type]]
}
#
#
proc is_gui_class {class} {
if {[$class getPropertyValue "referred_class"] == "" ||
[$class getPropertyValue "persistent"] == "1"} {
return 0
}
return 1
}
# return set prefix "o" in case ordered sets are needed
#
proc set_prefix {attrib} {
if [$attrib isOrdered] {
return o
} else {
return
}
}