gen::add_generator "C++" gen_cpp::generate
gen::add_generator "C" gen_cpp::generate_c

namespace eval gen_cpp {

variable src_file ""

variable keywords {
alignas
alignof
and
and_eq
asm
auto(1)
bitand
bitor
bool
break
case
catch
char
char16_t
char32_t
class
compl
const
constexpr
const_cast
continue
decltype
default(1)
delete(1)
do
double
dynamic_cast
else
enum
explicit
export(1)
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
noexcept
not
not_eq
nullptr
operator
or
or_eq
private
protected
public
register
reinterpret_cast
return
short
signed
sizeof
static
static_assert
static_cast
struct
switch
template
this
thread_local
throw
true
try
typedef
typeid
typename
union
unsigned
using(1)
virtual
void
volatile
wchar_t
while
xor
xor_eq 
}

# Autogenerated with DRAKON Editor 1.31

proc al { text } {
    #item 2749
    upvar 1 "lines" lines
    #item 2751
    lappend lines $text
}

proc append_sm_names { gdb } {
    #item 2286
    $gdb eval {
    	select diagram_id, original, name
    	from diagrams
    	where original is not null
    } {
    	set sm_name [ make_sm_name $original ]
    	set new_name "${sm_name}_$name"
    	$gdb eval {
    		update diagrams
    		set name = :new_name
    		where diagram_id = :diagram_id
    	}
    }
}

proc append_to_end { gdb diagram_id text } {
    #item 1962
    set end_ids [ $gdb eval {
    	select vertex_id
    	from vertices v
    	inner join links l on v.vertex_id = l.dst
    	where v.diagram_id = :diagram_id
    	and v.type = 'beginend'
    	group by vertex_id 
    } ]
    #item 1963
    if {[ llength $end_ids ] == 1} {
        #item 1967
        set end_id [ lindex $end_ids 0 ]
        #item 1968
        set new_id [ insert_vertex $gdb $diagram_id "action" $text ]
        #item 1969
        $gdb eval {
        	update links
        	set dst = :new_id
        	where dst = :end_id;
        }
        #item 1970
        gen::p.link $gdb $new_id 1 $end_id
    } else {
        #item 1971
        puts "end_ids: $end_ids"
        #item 1966
        set name [ diagram_name $gdb $diagram_id ]
        error "Diagram $name: can't find End..."
    }
}

proc build_g_declares { classes } {
    #item 2735
    set lines {}
    foreach class $classes {
        #item 2734
        lassign $class cname fields
        #item 2737
        lappend lines \
        "// Returns own"
        lappend lines \
        "$cname* ${cname}_create\(void\);"
        #item 2738
        lappend lines \
        "void ${cname}_destroy\("
        lappend lines \
        "    $cname* self // Takes ownership, can be null"
        lappend lines \
        "\);"
    }
    #item 2736
    return [ join $lines "\n" ]
}

proc build_g_impls { classes } {
    #item 2755
    set lines {}
    foreach class $classes {
        #item 2754
        lassign $class cname fields
        #item 2757
        al "$cname* ${cname}_create\(void\) \{"
        al "    $cname* self = allocate_memory\(sizeof\($cname\)\);"
        al "    self->base.type = &${cname}_t;"
        #item 2761
        g_impl_ctr $fields lines
        #item 2758
        al "    return self;"
        al "\}"
        #item 2759
        al "void ${cname}_destroy\("
        al "    $cname* self // takes ownership, can be null"
        al "\) \{"
        al "    if \(!self\) return;"
        al "    ENSURE\(self->base.type == &${cname}_t\)"
        #item 2762
        g_impl_dtr $fields lines
        #item 2760
        al "    free_memory\(self\, sizeof\($cname\)\);"
        al "\}"
    }
    #item 2756
    return [ join $lines "\n" ]
}

proc build_g_structures { classes } {
    #item 2724
    set lines {}
    foreach class $classes {
        #item 2723
        lassign $class cname fields
        #item 2726
        lappend lines \
        "typedef struct $cname \{"
        lappend lines \
        "    tobject base;"
        foreach field $fields {
            #item 2730
            set body [ field_body $field ]
            #item 2731
            lappend lines \
            "    $body;"
        }
        #item 2727
        lappend lines "\} $cname;"
    }
    #item 2725
    return [ join $lines "\n" ]
}

proc build_g_types { classes } {
    #item 2742
    set lines {}
    foreach class $classes {
        #item 2741
        lassign $class cname fields
        #item 2744
        al "static type_info_t ${cname}_t = \{"
        al "    OBJECT_SIGNATURE,"
        al "   \"$cname\","
        al "    \(destructor_fun\)${cname}_destroy"
        al "\};"
    }
    #item 2743
    return [ join $lines "\n" ]
}

proc build_gf_declare { fields } {
    #item 2614
    set lines {}
    #item 2611
    if {$fields == {}} {
        
    } else {
        #item 2616
        set init [ init_name ]
        #item 2618
        lappend lines \
         "void $init\(void\);"
        foreach field $fields {
            #item 2640
            set body [ field_body $field ]
            #item 2639
            #lappend lines "extern $body;"
        }
    }
    #item 2615
    return [ join $lines "\n" ]
}

proc build_gf_impl { fields } {
    #item 2668
    set lines {}
    #item 2667
    if {$fields == {}} {
        
    } else {
        #item 2675
        lappend lines \
         "static int g_module_initialised = 0;"
        foreach field $fields {
            #item 2679
            set body [ field_body $field ]
            #item 2680
            set own [ dict get $field "own" ]
            set value [ dict get $field "value" ]
            #item 2681
            if {$own} {
                #item 2685
                set ivalue " = 0"
            } else {
                #item 2698
                if {$value == ""} {
                    #item 2700
                    set ivalue ""
                } else {
                    #item 2684
                    set ivalue " = $value"
                }
            }
            #item 2678
            lappend lines \
             "static $body$ivalue;"
        }
        #item 2686
        set init [ init_name ]
        #item 2687
        lappend lines \
         "void $init\(void\) \{"
        #item 2689
        lappend lines \
        "    if \(g_module_initialised\) return;"
        #item 2690
        lappend lines \
        "    g_module_initialised = 1;"
        foreach field $fields {
            #item 2694
            set own [ dict get $field "own" ]
            set value [ dict get $field "value" ]
            set name [ dict get $field "name" ]
            set type [ dict get $field "type" ]
            #item 2695
            if {$own} {
                #item 2701
                lappend lines \
                "    $name = ${type}_create\($value\);"
            } else {
                
            }
        }
        #item 2688
        lappend lines "\}"
    }
    #item 2671
    return [ join $lines "\n" ]
}

proc build_globals { globals } {
    #item 2374
    set all_classes [ parse_globals $globals ]
    #item 2600
    lassign \
    [separate_globals $all_classes] \
    gfields classes
    #item 2376
    ensure_fields_unique $classes
    #item 2598
    set gf_declare [ build_gf_declare $gfields ]
    set gf_impl [ build_gf_impl $gfields ]
    #item 2377
    set structs [ build_g_structures $classes ]
    #item 2378
    set decls [ build_g_declares $classes ]
    #item 2379
    set types [ build_g_types $classes ]
    #item 2380
    set impls [ build_g_impls $classes ]
    #item 2381
    set header_parts [ list $structs $decls $gf_declare ]
    set body_parts [ list $types $impls $gf_impl ]
    #item 2382
    set header [ join $header_parts "\n" ]
    set body [ join $body_parts "\n" ]
    #item 2383
    return [ list $header $body ]
}

proc build_sm_body { gdb machines } {
    #item 2231
    set lines {}
    #item 2352
    if {$machines == {}} {
        
    } else {
        foreach machine $machines {
            #item 2239
            set states [ dict get $machine "states" ]
            set name [ dict get $machine "name" ]
            set machine_name [ make_sm_name $name ]
            #item 2240
            set i 1
            foreach state $states {
                #item 2242
                set const [ make_state_constant $name $state ]
                #item 2243
                lappend lines "#define $const $i"
                #item 2241
                incr i
            }
        }
        foreach machine $machines {
            #item 2252
            set parameters [ build_sm_cparams $machine ]
            set name [ dict get $machine "name" ]
            set machine_name [ make_sm_name $name ]
            #item 2266
            lappend lines \
             "typedef int \(*${machine_name}_callback\)\($parameters\);"
        }
        foreach machine $machines {
            #item 2271
            set states [ dict get $machine "states" ]
            set messages [ dict get $machine "messages" ]
            set name [ dict get $machine "name" ]
            set machine_name [ make_sm_name $name ]
            #item 2272
            set callback "${machine_name}_callback"
            foreach message $messages {
                #item 2273
                lappend lines \
                 "$callback ${machine_name}_${message}_methods\[\] = \{"
                #item 2275
                set cblist [ list "    0" ]
                foreach state $states {
                    #item 2811
                    set handler "${machine_name}_${state}_${message}"
                    #item 2818
                    if {[diagram_exists $gdb $handler]} {
                        #item 2276
                        lappend cblist "    $handler"
                    } else {
                        #item 2821
                        lappend cblist "    0"
                    }
                }
                #item 2277
                lappend lines [ join $cblist ",\n" ]
                #item 2274
                lappend lines "\};"
            }
        }
        foreach machine $machines {
            #item 2313
            set messages [ dict get $machine "messages" ]
            set parameters [ build_sm_params $machine ]
            set bare_params [ dict get $machine "parameters" ]
            set name [ dict get $machine "name" ]
            set machine_name [ make_sm_name $name ]
            #item 2321
            set states [ dict get $machine "states" ]
            set state_count [ llength $states ]
            foreach message $messages {
                #item 2317
                set method_lines [ print_sm_method \
                 $machine_name $parameters $bare_params \
                 $message $state_count ]
                #item 2348
                set lines [ concat $lines $method_lines ]
            }
        }
        #item 2351
        lappend lines \
         "int make_${machine_name}\(void\) \{ return 1; \}"
    }
    #item 2234
    return [ join $lines "\n" ]
}

proc build_sm_cparams { machine } {
    #item 2260
    set parameters [ dict get $machine "parameters" ]
    #item 2262
    if {$parameters == {}} {
        #item 2265
        return "void"
    } else {
        #item 2261
        return [ join $parameters ", " ]
    }
}

proc build_sm_header { machines } {
    #item 2199
    set lines {}
    #item 2355
    if {$machines == {}} {
        
    } else {
        foreach machine $machines {
            #item 2202
            set messages [ dict get $machine "messages" ]
            set parameters [ build_sm_params $machine ]
            set name [ dict get $machine "name" ]
            set machine_name [ make_sm_name $name ]
            #item 2217
            lappend lines "int make_${machine_name}\(void\);"
            foreach message $messages {
                #item 2213
                lappend lines \
                 "int ${machine_name}_${message}\($parameters\);"
            }
        }
    }
    #item 2214
    return [ join $lines "\n" ]
}

proc build_sm_params { machine } {
    #item 2208
    set parameters [ dict get $machine "parameters" ]
    #item 2210
    set parameters [ linsert $parameters 0 "int* machine" ]
    #item 2209
    return [ join $parameters ", " ]
}

proc change_state { next_state machine_name returns } {
    #item 2170
    if {$next_state == ""} {
        #item 2174
        return "return 999;"
    } else {
        #item 2193
        set const [ make_state_constant \
         $machine_name $next_state ]
        #item 2173
        return "return ${const};"
    }
}

proc check { keywords args } {
    foreach arg $args {
        #item 622
        upvar 1 $arg keyword
        #item 623
        if {[ contains $keywords $arg ]} {
            #item 625
            set keyword 1
        } else {
            #item 624
            set keyword 0
        }
    }
}

proc classify_keywords { keywords name } {
    #item 687
    set errors {}
    check $keywords abstract const inline
    #item 633
    set access [ find_keywords \
     $keywords { private public protected } ]
    #item 6480000
    set _sw6480000_ [ llength $access ]
    #item 6480001
    if {($_sw6480000_ == 0) || ($_sw6480000_ == 1)} {
        
    } else {
        #item 638
        lappend errors \
         "$name: inconsistent access: $access"
    }
    #item 640
    set dispatch [ find_keywords \
     $keywords { virtual static } ]
    #item 6610000
    set _sw6610000_ [ llength $dispatch ]
    #item 6610001
    if {$_sw6610000_ == 0} {
        #item 660
        set dispatch "normal"
    } else {
        #item 6610002
        if {$_sw6610000_ == 1} {
            
        } else {
            #item 653
            lappend errors \
             "$name: inconsistent dispatch: $dispatch"
        }
    }
    #item 671
    set subtype [ find_keywords $keywords \
      { function method ctr dtr signal slot} ]
    #item 6720000
    set _sw6720000_ [ llength $subtype ]
    #item 6720001
    if {$_sw6720000_ == 0} {
        #item 670
        set subtype "function"
    } else {
        #item 6720002
        if {$_sw6720000_ == 1} {
            
        } else {
            #item 663
            lappend errors \
             "$name: inconsistent procedure type: $subtype"
        }
    }
    #item 1212
    if {($inline) && ($abstract)} {
        #item 1216
        lappend errors \
        "$name: both inline and abstract is not allowed"
    } else {
        
    }
    #item 1217
    if {$abstract} {
        #item 1218
        set dispatch "virtual"
    } else {
        
    }
    #item 6740001
    if {$subtype == "function"} {
        #item 855
        if {$access == "protected"} {
            #item 859
            lappend errors \
            "$name: a function cannot be $access"
        } else {
            
        }
        #item 695
        if {$access == "public"} {
            #item 706
            if {$dispatch == "static"} {
                #item 699
                lappend errors \
                "$name: a function cannot be both public and static"
            } else {
                
            }
        } else {
            #item 713
            set access "static"
        }
        #item 703
        if {($dispatch == "normal") || ($dispatch == "static")} {
            
        } else {
            #item 704
            lappend errors \
            "$name: wrong dispatch: $dispatch"
        }
        #item 716
        if {$abstract} {
            #item 717
            lappend errors \
            "$name: a function cannot be abstract"
        } else {
            
        }
        #item 723
        if {$const} {
            #item 724
            lappend errors \
            "$name: a function cannot be const"
        } else {
            
        }
    } else {
        #item 6740002
        if {$subtype == "method"} {
            
        } else {
            #item 6740003
            if {$subtype == "ctr"} {
                #item 730
                if {$dispatch == "normal"} {
                    
                } else {
                    #item 731
                    lappend errors \
                    "$name: constructor cannot be $dispatch"
                }
                #item 734
                if {$const} {
                    #item 735
                    lappend errors \
                    "$name: constructor cannot be const"
                } else {
                    
                }
                #item 738
                if {$abstract} {
                    #item 739
                    lappend errors \
                    "$name: constructor cannot be abstract"
                } else {
                    
                }
            } else {
                #item 6740004
                if {$subtype == "dtr"} {
                    #item 7530001
                    if {$dispatch == "normal"} {
                        #item 759
                        set dispatch "virtual"
                    } else {
                        #item 7530002
                        if {$dispatch == "virtual"} {
                            
                        } else {
                            #item 746
                            lappend errors \
                            "$name: destructor cannot be $dispatch"
                        }
                    }
                    #item 760
                    if {$const} {
                        #item 761
                        lappend errors \
                        "$name: destructor cannot be const"
                    } else {
                        
                    }
                    #item 764
                    if {$abstract} {
                        #item 765
                        lappend errors \
                        "$name: destructor cannot be abstract"
                    } else {
                        
                    }
                    #item 7710001
                    if {$access == ""} {
                        #item 776
                        set access "public"
                    } else {
                        #item 7710002
                        if {$access == "public"} {
                            
                        } else {
                            #item 768
                            lappend errors \
                            "$name: destructor cannot be $access"
                        }
                    }
                } else {
                    #item 6740005
                    if {$subtype == "signal"} {
                        #item 784
                        if {$dispatch == "normal"} {
                            
                        } else {
                            #item 788
                            lappend errors \
                            "$name: a signal cannot be virtual or static"
                        }
                        #item 1230
                        if {$const} {
                            #item 1231
                            lappend errors \
                            "$name: signal cannot be const"
                        } else {
                            
                        }
                        #item 1234
                        if {$abstract} {
                            #item 1235
                            lappend errors \
                            "$name: signal cannot be abstract"
                        } else {
                            
                        }
                        #item 1244
                        set access "public"
                        set inline 0
                    } else {
                        #item 6740006
                        if {($subtype == "slot") && ($dispatch == "static")} {
                            #item 1224
                            lappend errors \
                            "$name: a slot cannot be static"
                        } else {
                            
                        }
                    }
                }
            }
        }
    }
    #item 749
    if {$access == ""} {
        #item 750
        set access "private"
    } else {
        
    }
    #item 778
    array set props {}
    #item 779
    set props(access) $access
    set props(dispatch) $dispatch
    set props(type) $subtype
    set props(abstract) $abstract
    set props(const) $const
    set props(inline) $inline
    #item 780
    set proplist [ array get props ]
    set error_message [ join $errors "\n" ]
    #item 781
    return [ list $error_message $proplist ]
}

proc clean_params { text } {
    #item 1541
    set raw_lines [ split $text "\n" ]
    #item 1555
    set wo_comments [ lmap $raw_lines gen_cpp::strip_comment ]
    #item 1556
    return [ non_empty_lines $wo_comments ]
}

proc commentator { text } {
    #item 143
    return "// $text"
}

proc create_jump { gdb diagram_id branches vertex_id dname } {
    #item 1931
    set count [ llength $branches ]
    #item 1932
    set branch [ find_branch $branches $vertex_id ]
    #item 1952
    set header [ get_value $branch header ]
    set header_text [ gen::p.vertex_text $gdb $header ]
    #item 1934
    set ordinal [ get_value $branch ordinal ]
    #item 1935
    if {$ordinal == $count} {
        #item 1955
        set text "self->State = 0;"
    } else {
        #item 1938
        if {[ is_receiving_branch $branch ]} {
            #item 1953
            set name [ state_info_name $dname $header_text ]
            #item 1954
            set text "self->State = &$name;"
        } else {
            #item 1950
            set name [ state_fun_name $dname $header_text ]
            #item 1951
            set text "${name}\(self\);"
        }
    }
    #item 1956
    return [ insert_vertex \
     $gdb $diagram_id "action" $text ]
}

proc delete_diagram { gdb diagram_id } {
    #item 1756
    $gdb eval {
    	delete from branches 
    	where diagram_id = :diagram_id;
    
    	delete from diagrams
    	where diagram_id = :diagram_id;
    }
}

proc diagram_exists { gdb name } {
    #item 2817
    return [ $gdb onecolumn {
    	select count(*)
    	from diagrams
    	where name = :name
    } ]
}

proc diagram_name { gdb diagram_id } {
    #item 1425
    set name [ $gdb onecolumn {
    	select name
    	from diagrams
    	where diagram_id = :diagram_id } ]
    #item 1426
    return $name
}

proc ensure_fields_unique { classes } {
    #item 2711
    set all_fields {}
    foreach class $classes {
        #item 2712
        lassign $class cname fields
        foreach field $fields {
            #item 2718
            set name [ dict get $field "name" ]
            #item 2715
            if {[contains $all_fields $name]} {
                #item 2719
                error "Field $cname.$name has a non-unique name"
            } else {
                #item 2720
                lappend all_fields $name
            }
        }
    }
}

proc extract_class_name { section } {
    #item 1202
    set section [ string map { "\{" " " } $section ]
    #item 944
    set lines [ split $section "\n" ]
    foreach line $lines {
        #item 946
        if {[ llength $line ] >= 2} {
            #item 947
            set first [ lindex $line 0 ]
            set second [ lindex $line 1 ]
            #item 948
            if {($first == "class") || ($first == "struct")} {
                #item 956
                return [ string map { ":" "" } $second ]
            } else {
                
            }
        } else {
            
        }
    }
    #item 955
    return ""
}

proc extract_copying { section } {
    #item 879
    set lines [ split $section "\n" ]
    
    set normal_878 1
    foreach line $lines {
        #item 880
        set value [ get_property $line "copying" ]
        #item 881
        if {$value == ""} {
            
        } else {
            #item 887
            if {$value == "yes"} {
                #item 888
                return 1
            } else {
                #item 886
                return 0
            }
            set normal_878 0
            break
        }
    }
    if {$normal_878 == 1} {
        #item 885
        return 0
    }
}

proc extract_return_type { text } {
    #item 491
    set skip [ string length "returns " ]
    set raw [ string range $text $skip end ]
    return [ string trim $raw ]
}

proc extract_signature { text name } {
    #item 783
    array set props { access static abstract 0
     inline 0 dispatch normal const 0 type function }
    set error_message ""
    set parameters {}
    set type "function"
    set returns ""
    #item 15
    set lines [ gen::separate_from_comments $text ]
    #item 17
    if {[ llength $lines ] == 0} {
        #item 833
        set returns "void"
    } else {
        #item 16
        set first_line [ lindex $lines 0 ]
        set first [ lindex $first_line 0 ]
        #item 589
        if {$first == "#comment"} {
            #item 42
            set type comment
            set returns ""
        } else {
            #item 595
            set keywords { 
            	public private protected
            	virtual static
            	inline abstract const
            	method function ctr dtr 
            	signal slot }
            #item 596
            set found_keywords \
             [ find_keywords $first $keywords ]
            #item 594
            if {[ llength $found_keywords ] == 0} {
                #item 598
                set start_index 0
                #item 34
                set count [ llength $lines ]
                set last [ expr { $count - 1 } ]
                #item 370001
                set i $start_index
                while { 1 } {
                    #item 370002
                    if {$i < $count} {
                        
                    } else {
                        break
                    }
                    #item 36
                    set current [ lindex $lines $i ]
                    set stripped [ lindex $current 0 ]
                    #item 46
                    if {[ string match "returns *" $stripped ]} {
                        #item 47
                        if {$i == $last} {
                            #item 50
                            set returns [ extract_return_type $stripped ]
                        } else {
                            #item 52
                            set error_message \
                            "$name: 'returns' can only be the last line."
                        }
                        break
                    } else {
                        
                    }
                    #item 45
                    lappend parameters $current
                    #item 370003
                    incr i
                }
                #item 834
                if {($type == "ctr") || ($type == "dtr")} {
                    #item 838
                    if {$returns == ""} {
                        
                    } else {
                        #item 839
                        set error_message \
                        "$name: constructors and destructors must not have return type"
                    }
                } else {
                    #item 842
                    if {$returns == ""} {
                        #item 845
                        set returns "void"
                    } else {
                        
                    }
                }
            } else {
                #item 597
                set start_index 1
                #item 600
                set alien_keywords \
                 [ find_not_belonging $first $keywords ]
                #item 601
                if {[ llength $alien_keywords ] == 0} {
                    #item 790
                    lassign [ classify_keywords $found_keywords $name ] \
                    	error_message prop_list
                    #item 791
                    if {$error_message == ""} {
                        #item 792
                        array unset props
                        array set props $prop_list
                        set type $props(type)
                        #item 34
                        set count [ llength $lines ]
                        set last [ expr { $count - 1 } ]
                        #item 370001
                        set i $start_index
                        while { 1 } {
                            #item 370002
                            if {$i < $count} {
                                
                            } else {
                                break
                            }
                            #item 36
                            set current [ lindex $lines $i ]
                            set stripped [ lindex $current 0 ]
                            #item 46
                            if {[ string match "returns *" $stripped ]} {
                                #item 47
                                if {$i == $last} {
                                    #item 50
                                    set returns [ extract_return_type $stripped ]
                                } else {
                                    #item 52
                                    set error_message \
                                    "$name: 'returns' can only be the last line."
                                }
                                break
                            } else {
                                
                            }
                            #item 45
                            lappend parameters $current
                            #item 370003
                            incr i
                        }
                        #item 834
                        if {($type == "ctr") || ($type == "dtr")} {
                            #item 838
                            if {$returns == ""} {
                                
                            } else {
                                #item 839
                                set error_message \
                                "$name: constructors and destructors must not have return type"
                            }
                        } else {
                            #item 842
                            if {$returns == ""} {
                                #item 845
                                set returns "void"
                            } else {
                                
                            }
                        }
                    } else {
                        
                    }
                } else {
                    #item 602
                    set error_message \
                        "$name: Unexpected keywords: $alien_keywords"
                }
            }
        }
    }
    #item 846
    if {($type == "dtr") && ([ llength $parameters ] > 0)} {
        #item 850
        set error_message \
        "$name: destructor cannot have parameters"
    } else {
        
    }
    #item 793
    set prop_list [ array get props ]
    #item 38
    return [ list $error_message \
    [ gen::create_signature $type $prop_list $parameters $returns ] ]
}

proc extract_sm_methods { gdb diagram_id } {
    #item 1595
    set name [ diagram_name $gdb $diagram_id ]
    #item 1372
    has_branches $gdb $diagram_id
    #item 1373
    has_receive $gdb $diagram_id
    #item 1431
    receives_in_the_middle $gdb $diagram_id
    #item 1432
    receives_are_first $gdb $diagram_id
    #item 1396
    returns_void $gdb $diagram_id
    #item 1526
    set lines [ get_params_lines $gdb $diagram_id ]
    #item 1557
    set last_line [ lindex $lines end ]
    #item 1558
    if {[ is_message_spec $last_line ]} {
        #item 1562
        set arg_lines [ lrange $lines 1 end-1 ]
        set msg_line $last_line
    } else {
        #item 1561
        set arg_lines [ lrange $lines 1 end ]
        set msg_line "receives Message* msg"
    }
    #item 1574
    set message_spec [ parse_message_spec $msg_line $name ]
    #item 1575
    set arguments [ lmap_user $arg_lines \
      gen_cpp::parse_argument $name ]
    #item 1608
    set max_branch [ $gdb onecolumn {
    	select max(ordinal)
    	from branches
    	where diagram_id = :diagram_id } ]
    #item 1609
    set branches {}
    #item 16100001
    set i 1
    while { 1 } {
        #item 16100002
        if {$i <= $max_branch} {
            
        } else {
            break
        }
        #item 1612
        lappend branches [ read_branch $gdb $diagram_id $i ]
        #item 16100003
        incr i
    }
    #item 1613
    set last_branch [ lindex $branches end ]
    set last_branch_header [ get_value $last_branch header ]
    #item 1633
    set init_branch [ lindex $branches 0 ]
    set cleanup_branch [ lindex $branches end ]
    set middle_branches [ lrange $branches 1 end-1 ]
    #item 1632
    lassign [ lpartition $middle_branches \
     gen_cpp::is_receiving_branch ] receiving normal
    #item 1634
    set fields [ make_init $gdb $init_branch $branches \
     $diagram_id $arguments ]
    #item 1635
    make_cleanup $gdb $cleanup_branch $branches \
     $diagram_id $fields
    foreach branch $normal {
        #item 1638
        make_sub_diagram $gdb $branch $branches $name 0 ""
    }
    foreach branch $receiving {
        #item 2049
        make_sub_diagram $gdb $branch $branches $name 1 $message_spec
    }
    #item 2096
    make_on_message $gdb $name $message_spec
    #item 2117
    set mname "${name}OnMessageFun"
    #item 2118
    set return_value { "void" "" }
    #item 2115
    set self [ st::sfield "$name*" self "" ]
    #item 2116
    set args [ list $self $message_spec ]
    #item 2119
    set comment "OnMessage callback for $name"
    #item 2120
    set on_message [ st::ssignature $mname $return_value $args $comment ]
    #item 2122
    set comment "Structure for $name state machine."
    #item 2123
    set code [ make_code $gdb $name $receiving ]
    #item 2133
    set sfields [ lmap $fields gen_cpp::table_field_to_struct ]
    #item 2121
    set sm_structure [ st::sstruct \
    $name \
    $sfields \
    {} \
    {} \
    1 \
    $comment \
    [ list $on_message ] \
    $code ]
    #item 2124
    put_value sm_structure on_message 1
    #item 1642
    delete_diagram $gdb $diagram_id
    #item 1347
    return $sm_structure
}

proc field_body { field } {
    #item 2633
    set name [ dict get $field "name" ]
    set type [ dict get $field "type" ]
    set own [ dict get $field "own" ]
    #item 2635
    if {$own} {
        #item 2638
        return "$type* $name"
    } else {
        #item 2634
        return "$type $name"
    }
}

proc filter_functions { functions inline access } {
    #item 1082
    set result {}
    foreach function $functions {
        #item 1085
        lassign $function diagram_id name signature body
        lassign $signature type prop_list parameters returns
        array set props $prop_list
        #item 1086
        if {($props(inline) == $inline) && ($props(access) == $access)} {
            #item 1088
            lappend result $function
        } else {
            
        }
    }
    #item 1083
    return $result
}

proc filter_methods { functions access } {
    #item 1097
    set result {}
    foreach function $functions {
        #item 1100
        lassign $function diagram_id name signature body
        lassign $signature type prop_list parameters returns
        array set props $prop_list
        #item 1102
        if {$props(access) == $access} {
            #item 1103
            lappend result $function
        } else {
            
        }
    }
    #item 1098
    return $result
}

proc find_branch { branches vertex_id } {
    foreach branch $branches {
        #item 1917
        set header [ get_value $branch header ]
        #item 1918
        if {$header == $vertex_id} {
            #item 1933
            return $branch
            #item 1916
            set ordinal [ get_value $branch ordinal ]
            #item 1922
            if {$ordinal == $count} {
                #item 1925
                return "last"
            } else {
                #item 1926
                if {[ is_receiving_branch $branch ]} {
                    #item 1929
                    return "receiving"
                } else {
                    #item 1928
                    return "normal"
                }
            }
            break
        } else {
            
        }
    }
    #item 1921
    error "Not found"
}

proc find_keywords { list keywords } {
    #item 804
    set result {}
    foreach keyword $keywords {
        #item 807
        if {[ contains $list $keyword ]} {
            #item 808
            lappend result $keyword
        } else {
            
        }
    }
    #item 1171
    if {$result == "const"} {
        
    } else {
        #item 805
        return $result
    }
}

proc find_not_belonging { list keywords } {
    #item 817
    set result {}
    foreach item $list {
        #item 820
        if {[ contains $keywords $item ]} {
            
        } else {
            #item 823
            lappend result $item
        }
    }
    #item 818
    return $result
}

proc g_impl_ctr { fields lines_var } {
    #item 2768
    upvar 1 $lines_var lines
    foreach field $fields {
        #item 2771
        set own [ dict get $field "own" ]
        set name [ dict get $field "name" ]
        set value [ dict get $field "value" ]
        set type [ dict get $field "type" ]
        #item 2772
        if {$own} {
            #item 2775
            al "    self->$name = ${type}_create\($value\);"
        } else {
            #item 2777
            if {$value == ""} {
                
            } else {
                #item 2776
                al "    self->$name = $value;"
            }
        }
    }
}

proc g_impl_dtr { fields lines_var } {
    #item 2784
    upvar 1 $lines_var lines
    foreach field $fields {
        #item 2787
        set own [ dict get $field "own" ]
        set name [ dict get $field "name" ]
        set type [ dict get $field "type" ]
        #item 2788
        if {$own} {
            #item 2791
            al "    ${type}_destroy\(self->$name\);"
        } else {
            
        }
    }
}

proc generate { db gdb filename } {
    #item 964
    p.generate $db $gdb $filename "cpp"
}

proc generate_body { gdb diagram_id start_item node_list items incoming } {
    #item 1262
    set callbacks [ gen_cpp::make_callbacks "C++" ]
    #item 1261
    generate_body_goto \
    $gdb $diagram_id $start_item $node_list $items $incoming \
    $callbacks
}

proc generate_c { db gdb filename } {
    #item 977
    p.generate $db $gdb $filename "c"
}

proc get_field_list { gdb first diagram_id } {
    #item 1702
    set name [ diagram_name $gdb $diagram_id ]
    #item 1691
    set first_type [ gen::p.vertex_type $gdb $first ]
    #item 1692
    if {$first_type == "action"} {
        
    } else {
        #item 1695
        set msg "Diagram $name: the first icon "
        append msg "of a state machine must be "
        append msg "an action icon with fields."
        error $msg
    }
    #item 1696
    set first_text [ gen::p.vertex_text $gdb $first ]
    #item 1697
    set lines [ clean_params $first_text ]
    #item 1698
    if {[ llength $lines ] == 0} {
        #item 1701
        set msg "Diagram $name: empty fields list."
        error $msg
    } else {
        
    }
    #item 1703
    set fields [ lmap_user $lines \
     gen_cpp::parse_field $name ]
    #item 1748
    return $fields
}

proc get_params { gdb diagram_id } {
    #item 1390
    set params_icon [ $gdb onecolumn {
    	select params_icon
    	from branches
    	where diagram_id = :diagram_id
    	and ordinal = 1 } ]
    #item 1391
    set text [ gen::p.vertex_text $gdb $params_icon ]
    #item 1392
    return [ string trim $text ]
}

proc get_params_lines { gdb diagram_id } {
    #item 1604
    set params_icon [ $gdb onecolumn {
    	select params_icon
    	from branches
    	where diagram_id = :diagram_id
    	and ordinal = 1 } ]
    #item 1605
    set params_text [ gen::p.vertex_text $gdb $params_icon ]
    #item 1606
    set lines [ clean_params $params_text ]
    #item 1607
    return $lines
}

proc get_property { line key } {
    #item 870
    set eq_position [ string first "=" $line ]
    #item 872
    if {$eq_position == -1} {
        #item 875
        return ""
    } else {
        #item 871
        set name [ string range $line 0 $eq_position-1 ]
        set value [ string range $line $eq_position+1 end ]
        set name [ string trim $name ]
        set value [ string trim $value ]
        #item 874
        if {$name == $key} {
            #item 873
            return $value
        } else {
            #item 875
            return ""
        }
    }
}

proc get_returns { gdb } {
    
}

proc get_single_line { block } {
    #item 1281
    set lines [ split $block "\n" ]
    foreach line $lines {
        #item 1284
        set trimmed [ string trim $line ]
        #item 1286
        if {$trimmed == ""} {
            
        } else {
            #item 1289
            return $trimmed
        }
    }
    #item 1285
    return ""
}

proc has_branches { gdb diagram_id } {
    #item 1355
    set count [ $gdb onecolumn {
    	select count(*)
    	from branches
    	where diagram_id = :diagram_id } ]
    #item 1356
    if {$count < 2} {
        #item 1359
        set name [ diagram_name $gdb $diagram_id ]
        #item 1360
        error "Diagram $name is a state machine and must be a silhouette."
    } else {
        
    }
}

proc has_receive { gdb diagram_id } {
    #item 1365
    set count [ $gdb onecolumn {
    	select count(*)
    	from vertices
    	where diagram_id = :diagram_id
    	and type = 'action'
    	and text = 'RECEIVE' } ]
    #item 1367
    if {$count == 0} {
        #item 1429
        set name [ diagram_name $gdb $diagram_id ]
        #item 1371
        error "Diagram $name is a state machine and must have at least one RECEIVE icon."
    } else {
        
    }
}

proc has_value { field } {
    #item 1765
    set value [ get_value $field value ]
    #item 1766
    if {$value == ""} {
        #item 1769
        return 0
    } else {
        #item 1770
        return 1
    }
}

proc highlight { tokens } {
    #item 2827
    variable keywords
    #item 2828
    return [ gen_cs::highlight_generic $keywords $tokens ]
}

proc init_field { field } {
    #item 1795
    set name [ get_value $field name ]
    set value [ get_value $field value ]
    #item 1796
    return "self->$name = $value;"
}

proc init_name { } {
    #item 2624
    variable src_file
    #item 2807
    set module_name [ take_module_name $src_file ]
    #item 2625
    return "${module_name}_init"
}

proc insert_vertex { gdb diagram_id type text } {
    #item 1515
    set vertex_id [ mod::next_key $gdb vertices vertex_id ]
    #item 1973
    set item_id [ mod::next_key $gdb vertices item_id ]
    #item 1516
    $gdb eval {
    	insert into vertices
    		(vertex_id, diagram_id, type, text, marked, item_id )
    	values  (:vertex_id, :diagram_id, :type, :text, 0, :item_id)
    }
    #item 1517
    return $vertex_id
}

proc is_message_spec { text } {
    #item 1568
    if {([ llength $text ] >= 2) && ([ lindex $text 0 ] == "receives")} {
        #item 1571
        return 1
    } else {
        #item 1572
        return 0
    }
}

proc is_own { field } {
    #item 2033
    set type [ get_value $field type ]
    #item 2036
    if {$type == "own"} {
        #item 2034
        return 1
    } else {
        #item 2035
        return 0
    }
}

proc is_receive { gdb vertex_id } {
    #item 1451
    lassign [ $gdb eval {
    	select type, text
    	from vertices
    	where vertex_id = :vertex_id } ] type text
    #item 1452
    if {($type == "action") && ($text == "RECEIVE")} {
        #item 1456
        return 1
    } else {
        #item 1457
        return 0
    }
}

proc is_receiving_branch { branch } {
    #item 1628
    return [ get_value $branch receiving ]
}

proc is_state_machine { diagram_id gdb } {
    #item 1298
    lassign [ gen::get_diagram_start $gdb $diagram_id ] start params_icon
    #item 1299
    if {$params_icon == {}} {
        #item 1308
        return 0
    } else {
        #item 1302
        set text [ gen::p.vertex_text $gdb $params_icon ]
        #item 1304
        if {$text == ""} {
            #item 1308
            return 0
        } else {
            #item 1303
            set lines [ split $text "\n" ]
            #item 1306
            set fline [ lindex $lines 0 ]
            set text [ string trim $fline ]
            #item 1305
            if {$text == "state machine"} {
                #item 1307
                return 1
            } else {
                #item 1308
                return 0
            }
        }
    }
}

proc isolate_branch { gdb branches branch name } {
    set diagram_id -1
    
    set _next_item_ 1820
    while { 1 } {
        if {$_next_item_ == 1820} {
            set first_branch [ lindex $branches 0 ]
            set _next_item_ 1821
    
        } elseif {$_next_item_ == 1821} {
            set first_header [ get_value $first_branch header ]
            set _next_item_ 1822
    
        } elseif {$_next_item_ == 1822} {
            set end ""
            set visited {}
            set _next_item_ 2040
    
        } elseif {$_next_item_ == 2040} {
            set my_header [ get_value $branch header ]
            set _next_item_ 1823
    
        } elseif {$_next_item_ == 1823} {
            set stack {}
            lappend stack $my_header
            set _next_item_ 1824
    
        } elseif {$_next_item_ == 1824} {
            set current [ lindex $stack end ]
            set stack [ lrange $stack 0 end-1 ]
            set _next_item_ 1834
    
        } elseif {$_next_item_ == 1834} {
            set next_links [ $gdb eval {
            	select ordinal
            	from links
            	where src = :current } ]
            set _next_item_ 18350001
    
        } elseif {$_next_item_ == 18350001} {
            set _col1835 $next_links
            set _len1835 [ llength $_col1835 ]
            set _ind1835 0
            set _next_item_ 18350002
    
        } elseif {$_next_item_ == 18350002} {
            if {$_ind1835 < $_len1835} {
                #item 18350004
                set ordinal [ lindex $_col1835 $_ind1835 ]
                set _next_item_ 1840
            } else {
                set _next_item_ 1825
            }
    
        } elseif {$_next_item_ == 1840} {
            set next [ gen::p.link_dst \
             $gdb $current $ordinal ]
            set _next_item_ 1828
    
        } elseif {$_next_item_ == 1828} {
            if {$next == $first_header} {
                #item 1832
                set msg "Diagram $name: cannot jump to the first branch "
                append msg "of state machine."
                set _next_item_ 1833
            } else {
                #item 1841
                set type [ gen::p.vertex_type $gdb $next ]
                set _next_item_ 18420001
            }
    
        } elseif {$_next_item_ == 1833} {
            error $msg
            set _next_item_ 1984
    
        } elseif {$_next_item_ == 18420001} {
            if {$type == "beginend"} {
                set _next_item_ 1850
            } else {
                set _next_item_ 18420002
            }
    
        } elseif {$_next_item_ == 1850} {
            if {$end == ""} {
                #item 1852
                set end $next
                set_diagram $gdb $next $diagram_id
                set _next_item_ 18350003
            } else {
                set _next_item_ 18350003
            }
    
        } elseif {$_next_item_ == 18420002} {
            if {$type == "branch"} {
                #item 1867
                set jump [ create_jump $gdb $diagram_id \
                 $branches $next $name ]
                set _next_item_ 1864
            } else {
                set _next_item_ 1859
            }
    
        } elseif {$_next_item_ == 1864} {
            if {$end == ""} {
                #item 1866
                set end [ insert_vertex $gdb $diagram_id \
                 "beginend" "End" ]
                set _next_item_ 1869
            } else {
                set _next_item_ 1869
            }
    
        } elseif {$_next_item_ == 1869} {
            gen::p.set_link_dst $gdb $current $ordinal $jump
            gen::p.link $gdb $jump 1 $end
            set _next_item_ 18350003
    
        } elseif {$_next_item_ == 1859} {
            if {[ contains $visited $next ]} {
                set _next_item_ 18350003
            } else {
                #item 1862
                lappend visited $next
                set _next_item_ 1863
            }
    
        } elseif {$_next_item_ == 1863} {
            set_diagram $gdb $next $diagram_id
            set _next_item_ 1870
    
        } elseif {$_next_item_ == 1870} {
            lappend stack $next
            set _next_item_ 18350003
    
        } elseif {$_next_item_ == 18350003} {
            incr _ind1835
            set _next_item_ 18350002
    
        } elseif {$_next_item_ == 1825} {
            if {[ llength $stack ] == 0} {
                set _next_item_ 1984
            } else {
                set _next_item_ 1824
            }
    
        } elseif {$_next_item_ == 1984} {
            return [ gen::p.link_dst $gdb $my_header 1 ]
    
        }
    }
}

proc make_callbacks { language } {
    #item 1192
    set callbacks {}
    #item 1194
    gen::put_callback callbacks assign			gen_c::assign
    gen::put_callback callbacks compare			gen_c::compare
    gen::put_callback callbacks compare2		gen_c::compare
    gen::put_callback callbacks bad_case		gen_c::bad_case
    gen::put_callback callbacks tag		gen_c::tag
    
    gen::put_callback callbacks body			gen_c::generate_body
    gen::put_callback callbacks signature		gen_cpp::extract_signature
    gen::put_callback callbacks and				gen_c::p.and
    gen::put_callback callbacks or				gen_c::p.or
    gen::put_callback callbacks not				gen_c::p.not
    gen::put_callback callbacks declare				gen_c::declare
    #item 1263
    gen::put_callback callbacks if_start		gen_c::if_start
    gen::put_callback callbacks if_end		gen_c::if_end
    gen::put_callback callbacks else_start		gen_c::else_start
    gen::put_callback callbacks block_close		gen_c::block_close
    gen::put_callback callbacks return_none		gen_c::return_none
    gen::put_callback callbacks goto		gen_c::goto
    gen::put_callback callbacks shelf		gen_c::shelf
    gen::put_callback callbacks change_state 	gen_cpp::change_state
    gen::put_callback callbacks shutdown ""
    gen::put_callback callbacks fsm_merge   0
    gen::put_callback callbacks can_glue 1
    gen::put_callback callbacks exit_door "exit_door:;"
    #item 1199
    if {$language == "c"} {
        #item 1197
        gen::put_callback callbacks comment gen_c::commentator
    } else {
        #item 1198
        gen::put_callback callbacks comment gen_cpp::commentator
    }
    #item 1193
    return $callbacks
}

proc make_cleanup { gdb branch branches diagram_id fields } {
    #item 2021
    set name [ diagram_name $gdb $diagram_id ]
    #item 2002
    set first [ get_value $branch first ]
    #item 2039
    set own_fields [ lfilter $fields gen_cpp::is_own ]
    #item 2013
    set params {}
    #item 2019
    lappend params "public"
    lappend params "$name* self"
    #item 2022
    set params_text [ join $params "\n" ]
    #item 2005
    set init_text "if \(!self\) return;"
    #item 2006
    set preface [ insert_vertex $gdb -1 "action" $init_text ]
    #item 2025
    set new_first [ isolate_branch $gdb $branches $branch $name ]
    #item 2048
    gen::p.relink $gdb $new_first $preface
    gen::p.link $gdb $preface 1 $new_first
    #item 2041
    set outro {}
    foreach field $own_fields {
        #item 2046
        set fname [ get_value $field name ]
        #item 2047
        lappend outro "Object_Destroy\(self->$fname\);"
    }
    #item 2042
    lappend outro "Allocator_Free\(self\);"
    #item 2043
    set outro_text [ join $outro "\n" ]
    #item 2026
    append_to_end $gdb -1 $outro_text
    #item 2023
    set dname "${name}_Destroy"
    #item 2024
    set new_dia [ make_diagram $gdb $dname $params_text $preface ]
    #item 2027
    move_dangling_to_diagram $gdb $new_dia
}

proc make_code { gdb name receiving } {
    #item 2152
    set lines {}
    #item 2159
    set state "${name}_State"
    #item 2154
    lappend lines "struct $state \{"
    lappend lines "    int Id;"
    lappend lines "    const char* Name;"
    lappend lines "    ${name}OnMessageFun Handler;"
    lappend lines "\};"
    lappend lines ""
    foreach branch $receiving {
        #item 2157
        set header_icon [ get_value $branch header ]
        set header [ gen::p.vertex_text $gdb $header_icon ]
        set ordinal [ get_value $branch ordinal ]
        #item 2158
        set fun [ state_fun_name $name $header ]
        set state_obj [ state_info_name $name $header ]
        #item 2160
        lappend lines "$state $state_obj = \{"
        lappend lines "    $ordinal,"
        lappend lines "    \"$header\","
        lappend lines "    $fun \};"
        lappend lines ""
    }
    #item 2153
    return [ join $lines "\n" ]
}

proc make_diagram { gdb name params first_vertex } {
    #item 1506
    set diagram_id [ mod::next_key $gdb diagrams diagram_id ]
    #item 1508
    $gdb eval {
    	insert into diagrams (diagram_id, name)
    	values (:diagram_id, :name) }
    #item 1518
    set start_icon [ insert_vertex $gdb $diagram_id "beginend" $name ]
    #item 1519
    set params_icon [ insert_vertex $gdb $diagram_id "action" $params ]
    #item 1985
    $gdb eval {
    	delete from links
    	where dst = :first_vertex
    }
    #item 1975
    gen::p.link $gdb $start_icon 1 $first_vertex
    #item 1520
    $gdb eval {
    	insert into branches
    		(diagram_id, ordinal, start_icon, params_icon, first_icon)
    	values (:diagram_id, 1, :start_icon, :params_icon, :first_vertex)
    }
    #item 1507
    return $diagram_id
}

proc make_identifier { text } {
    #item 1890
    set trimmed [ string trim $text ]
    #item 1891
    return [ string map { " " "_" "-" "_" } $trimmed ]
}

proc make_init { gdb init_branch branches diagram_id arguments } {
    #item 1789
    set name [ diagram_name $gdb $diagram_id ]
    #item 1758
    set first [ get_value $init_branch first ]
    #item 1749
    set fields [ get_field_list $gdb $first $diagram_id ]
    #item 2113
    set super [ list type value class Object name Super \
     comment "Base class" value "" ]
    set state [ list type value class "${name}_State*" name State \
     comment "Current state" value "" ]
    set fields [ linsert $fields 0 $super $state ]
    #item 1759
    set init_fields [ lfilter $fields gen_cpp::has_value ]
    #item 1788
    set init_lines {}
    lappend init_lines \
    "$name* self = \($name*\)Allocator_Allocate\(sizeof\($name\)\, 1);"
    lappend init_lines \
    "self->Super.Type = &g${name};"
    lappend init_lines \
    "self->State = 0;"
    #item 1771
    add_range init_lines [ lmap $init_fields gen_cpp::init_field ]
    #item 1772
    set init_text [ join $init_lines "\n" ]
    #item 1773
    $gdb eval {
    	update vertices
    	set text = :init_text
    	where vertex_id = :first
    }
    #item 1780
    set params {}
    #item 1781
    lappend params "public"
    foreach arg $arguments {
        #item 1785
        set type [ get_value $arg type ]
        set aname [ get_value $arg name ]
        #item 1784
        lappend params "$type $aname"
    }
    #item 1787
    lappend params "returns Object*"
    #item 1797
    set params_text [ join $params "\n" ]
    #item 1801
    set new_first [ isolate_branch $gdb $branches $init_branch $name ]
    #item 1802
    append_to_end $gdb -1 "return \(Object*\)self;"
    #item 1798
    set dname "${name}_Create"
    #item 1800
    set new_dia [ make_diagram $gdb $dname $params_text $new_first ]
    #item 1982
    move_dangling_to_diagram $gdb $new_dia
    #item 1750
    return $fields
}

proc make_on_message { gdb name message_spec } {
    #item 2103
    set type [ get_value $message_spec type ]
    set mname [ get_value $message_spec name ]
    #item 2102
    set lines {}
    lappend lines "public"
    lappend lines "$name* self"
    lappend lines "$type $mname"
    #item 2106
    set params_text [ join $lines "\n" ]
    #item 2104
    set lines {}
    lappend lines "${name}_State* state = self->State;"
    lappend lines "if \(state\) \{"
    lappend lines "    self->State = 0;"
    lappend lines "    state->Handler\(self, $mname\);"
    lappend lines "\}"
    #item 2105
    set body_text [ join $lines "\n" ]
    #item 2107
    set body [ insert_vertex $gdb -1 "action" $body_text ]
    #item 2108
    set end [ insert_vertex $gdb -1 "beginend" "End" ]
    #item 2109
    gen::p.link $gdb $body 1 $end
    #item 2111
    set dname "${name}_OnMessage"
    #item 2110
    set new_dia [ make_diagram $gdb $dname $params_text $body ]
    #item 2112
    move_dangling_to_diagram $gdb $new_dia
}

proc make_params_for_call { bare_params } {
    #item 2339
    set names {}
    foreach param $bare_params {
        #item 2343
        set parts [ split $param " " ]
        #item 2344
        lappend names [ lindex $param end ]
    }
    #item 2342
    return [ join $names ", " ]
}

proc make_sm_name { diagram_name } {
    #item 2180
    if {$diagram_name == "state machine"} {
        #item 2183
        return "state_machine"
    } else {
        #item 2184
        set last [ string range $diagram_name 3 end ]
        set name [ string trim $last ]
        #item 2185
        return $name
    }
}

proc make_state_constant { machine_name state } {
    #item 2191
    set name [ make_sm_name $machine_name ]
    set s "${name}_${state}"
    #item 2192
    return [ string toupper $s ]
}

proc make_sub_diagram { gdb branch branches name receiving message_spec } {
    #item 2079
    set new_first [ isolate_branch $gdb $branches $branch $name ]
    #item 2076
    set params_text "public\n$name* self\n"
    #item 2093
    if {$receiving} {
        #item 2092
        gen::p.set_vertex_text $gdb $new_first ""
        #item 2161
        set type [ get_value $message_spec type ]
        set mname [ get_value $message_spec name ]
        #item 2162
        append params_text "$type $mname"
    } else {
        
    }
    #item 2091
    set header [ get_value $branch header ]
    set header_text [ gen::p.vertex_text $gdb $header ]
    set dname [ state_fun_name $name $header_text ]
    #item 2078
    set new_dia [ make_diagram $gdb $dname $params_text $new_first ]
    #item 2081
    move_dangling_to_diagram $gdb $new_dia
}

proc move_dangling_to_diagram { gdb diagram_id } {
    #item 1981
    $gdb eval {
    	update vertices
    	set diagram_id = :diagram_id
    	where diagram_id = -1
    }
}

proc noncopyable { fhandle class_name } {
    #item 1184
    puts $fhandle "private:"
    puts $fhandle "    // non-copyable"
    puts $fhandle "    $class_name\(const $class_name& other\) \{\}"
    puts $fhandle "    void operator=\(const $class_name& other\) \{\}"
}

proc p.generate { db gdb filename language } {
    #item 2617
    variable src_file
    set src_file $filename
    #item 933
    set callbacks [ make_callbacks $language ]
    #item 2163
    set machines [ sma::extract_many_machines \
     $gdb $callbacks ]
    #item 2280
    append_sm_names $gdb
    #item 2833
    zap_cleanups $gdb
    #item 2215
    set sm_header [ build_sm_header $machines ]
    set sm_body [ build_sm_body $gdb $machines ]
    #item 2792
    tab::generate_tables $gdb $callbacks 0
    #item 1324
    set diagrams [ $gdb eval {
    	select diagram_id from diagrams } ]
    foreach diagram_id $diagrams {
        #item 1318
        gen::fix_graph_for_diagram $gdb $callbacks 1 $diagram_id
    }
    #item 923
    set sections { 
      h_header h_footer c_header c_footer class options
      structure globals
    }
    lassign [ gen::scan_file_description $db $sections ] \
      h_header h_footer c_header c_footer class options \
      structure globals
    #item 2359
    lassign \
    [build_globals $globals] \
    g_header g_body
    #item 905
    set functions [ gen::generate_functions $db $gdb  \
    	$callbacks 0 ]
    #item 895
    if {[ graph::errors_occured ]} {
        
    } else {
        #item 937
        if {$language == "cpp"} {
            #item 938
            set copying [ extract_copying $options ]
            set class_name [ extract_class_name $class ]
        } else {
            #item 957
            set copying 0
            set class_name ""
        }
        #item 2292
        set functions [ update_returns $gdb $functions ]
        #item 960
        lassign [ sort_functions $functions $language $class_name ] \
        free_funs \
        ctrs dtrs methods signals slots
        #item 928
        set h_filename [ replace_extension $filename "h" ]
        set c_filename [ replace_extension $filename $language ]
        set filenames [ list $h_filename $c_filename ]
        #item 929
        lassign [ open_files $filenames "w" ] hfile cfile
        #item 930
        catch {
            print_header $h_filename $hfile $free_funs \
            $ctrs $dtrs $methods $signals $slots \
            $h_header $h_footer $class $copying $class_name \
            $language $sm_header $g_header
            
            print_cpp $h_filename $cfile $free_funs \
            $ctrs $dtrs $methods $slots \
            $c_header $c_footer $class_name \
            $language $sm_body $g_body
        } error_message
        #item 931
        close_files [ list $hfile $cfile ]
        #item 896
        if {$error_message == ""} {
            
        } else {
            #item 897
            puts $::errorInfo
            error $error_message
        }
    }
}

proc parse_argument { line name } {
    #item 1582
    if {[ llength $line ] >= 2} {
        #item 1585
        set type [ lrange $line 0 end-1 ]
        set name [ lindex $line end ]
        #item 1586
        return [ list \
         type $type \
         name $name \
         comment "" ]
    } else {
        #item 1587
        error "Diagram $name: syntax error in arguments icon: $line"
    }
}

proc parse_field { line name } {
    #item 1727
    if {[ string match "*;" $line ]} {
        #item 1731
        set text [ string range $line 0 end-1 ]
        #item 1718
        set eq_pos [ string first "=" $text ]
        #item 1719
        if {$eq_pos == -1} {
            #item 1722
            set field $text
            set value ""
            #item 1735
            if {[ llength $field ] < 2} {
                #item 1730
                set msg "Diagram $name: syntax error in: $line"
                #item 1726
                error $msg
            } else {
                #item 1736
                set first [ lindex $field 0 ]
                #item 1737
                if {$first == "own"} {
                    #item 1739
                    if {[ llength $field ] == 3} {
                        #item 1742
                        set class [ lindex $field 1 ]
                        #item 1745
                        set type "own"
                        #item 2125
                        set fname [ lindex $field end ]
                    } else {
                        #item 1730
                        set msg "Diagram $name: syntax error in: $line"
                        #item 1726
                        error $msg
                    }
                } else {
                    #item 1743
                    set class [ lrange $field 0 end-1 ]
                    #item 1744
                    set type "value"
                    #item 2125
                    set fname [ lindex $field end ]
                }
            }
        } else {
            #item 1732
            set value_start $eq_pos
            set field_end $eq_pos
            incr value_start
            incr field_end -1
            #item 1733
            set field [ string range $text 0 $field_end ]
            set value [ string range $text $value_start end ]
            set value [ string trim $value ]
            #item 1734
            if {$value == ""} {
                #item 1730
                set msg "Diagram $name: syntax error in: $line"
                #item 1726
                error $msg
            } else {
                #item 1735
                if {[ llength $field ] < 2} {
                    #item 1730
                    set msg "Diagram $name: syntax error in: $line"
                    #item 1726
                    error $msg
                } else {
                    #item 1736
                    set first [ lindex $field 0 ]
                    #item 1737
                    if {$first == "own"} {
                        #item 1739
                        if {[ llength $field ] == 3} {
                            #item 1742
                            set class [ lindex $field 1 ]
                            #item 1745
                            set type "own"
                            #item 2125
                            set fname [ lindex $field end ]
                        } else {
                            #item 1730
                            set msg "Diagram $name: syntax error in: $line"
                            #item 1726
                            error $msg
                        }
                    } else {
                        #item 1743
                        set class [ lrange $field 0 end-1 ]
                        #item 1744
                        set type "value"
                        #item 2125
                        set fname [ lindex $field end ]
                    }
                }
            }
        }
    } else {
        #item 1730
        set msg "Diagram $name: syntax error in: $line"
        #item 1726
        error $msg
    }
    #item 1747
    return [ list \
     name $fname \
     type $type \
     class $class \
     generate "" \
     value $value \
     comment "" ]
}

proc parse_g_line { header line } {
    #item 2522
    set first_colon [ string first ":" $line ]
    set last [ string length $line ]
    incr last -1
    #item 25340001
    if {$first_colon == -1} {
        #item 2541
        error \
        "':' not found in '$line' inside $header"
    } else {
        #item 25340002
        if {$first_colon == 0} {
            #item 2545
            error \
            "'$line' begins with ':' inside $header"
        } else {
            #item 25340003
            if {$first_colon == $last} {
                #item 2546
                error \
                "Type missing in '$line' inside $header"
            } else {
                #item 2549
                set before_first \
                [expr {$first_colon - 1}]
                #item 2550
                set after_first \
                [expr {$first_colon + 1}]
                #item 2548
                set first [ string range $line 0 $before_first ]
                set second [ string range $line $after_first end ]
                #item 2551
                set name [ string trim $first ]
                #item 2553
                set second_colon [ string first ":" $second ]
                #item 25540001
                if {$second_colon == -1} {
                    #item 2561
                    set type [ string trim $second ]
                    set value ""
                    #item 2572
                    if {[string match "own *" $type]} {
                        #item 2575
                        set type [ string range $type 4 end ]
                        set type [ string trim $type ]
                        #item 2576
                        set own 1
                    } else {
                        #item 2577
                        set own 0
                    }
                    #item 2579
                    set result [ list "name" $name \
                     "type" $type \
                     "own" $own "value" $value ]
                } else {
                    #item 25540002
                    if {$second_colon == 0} {
                        #item 2562
                        error \
                        "Unexpected ':' in '$line' inside $header"
                    } else {
                        #item 2568
                        set before_second \
                        [expr {$second_colon - 1}]
                        #item 2569
                        set after_second \
                        [expr {$second_colon + 1}]
                        #item 2567
                        set p1 [ string range $second 0 $before_second ]
                        set p2 [ string range $second $after_second end ]
                        #item 2570
                        set type [ string trim $p1 ]
                        set value [ string trim $p2 ]
                        #item 2572
                        if {[string match "own *" $type]} {
                            #item 2575
                            set type [ string range $type 4 end ]
                            set type [ string trim $type ]
                            #item 2576
                            set own 1
                        } else {
                            #item 2577
                            set own 0
                        }
                        #item 2579
                        set result [ list "name" $name \
                         "type" $type \
                         "own" $own "value" $value ]
                    }
                }
            }
        }
    }
    #item 2580
    return $result
}

proc parse_globals { section } {
    set all_lines [ split $section "\n" ]
    set lines {}
    
    set _next_item_ 24810001
    while { 1 } {
        if {$_next_item_ == 24810001} {
            set _col2481 $all_lines
            set _len2481 [ llength $_col2481 ]
            set _ind2481 0
            set _next_item_ 24810002
    
        } elseif {$_next_item_ == 24810002} {
            if {$_ind2481 < $_len2481} {
                #item 24810004
                set line [ lindex $_col2481 $_ind2481 ]
                set _next_item_ 2483
            } else {
                #item 2438
                set i 0
                set length [ llength $lines ]
                set _next_item_ 2447
            }
    
        } elseif {$_next_item_ == 2483} {
            set trimmed [ string trim $line ]
            set _next_item_ 2484
    
        } elseif {$_next_item_ == 2484} {
            if {($trimmed == "") || ([string match "//*" $trimmed])} {
                set _next_item_ 24810003
            } else {
                #item 2488
                lappend lines $trimmed
                set _next_item_ 24810003
            }
    
        } elseif {$_next_item_ == 24810003} {
            incr _ind2481
            set _next_item_ 24810002
    
        } elseif {$_next_item_ == 2447} {
            set result {}
            set _next_item_ 2440
    
        } elseif {$_next_item_ == 2440} {
            if {$i < $length} {
                #item 2439
                set current [ lindex $lines $i ]
                incr i
                set _next_item_ 24890001
            } else {
                set _next_item_ 2516
            }
    
        } elseif {$_next_item_ == 24890001} {
            if {$current == "\{"} {
                #item 2498
                error "Unexpected '\{'"
                set _next_item_ 2516
            } else {
                set _next_item_ 24890002
            }
    
        } elseif {$_next_item_ == 24890002} {
            if {$current == "\}"} {
                #item 2499
                error "Unexpected '\}'"
                set _next_item_ 2516
            } else {
                #item 2448
                set header $current
                set fields {}
                set _next_item_ 2450
            }
    
        } elseif {$_next_item_ == 2450} {
            if {$i < $length} {
                #item 2449
                set current [ lindex $lines $i ]
                incr i
                set _next_item_ 25000001
            } else {
                #item 2480
                error "Unexpected end after $header"
                set _next_item_ 2516
            }
    
        } elseif {$_next_item_ == 25000001} {
            if {$current == "\{"} {
                set _next_item_ 2463
            } else {
                set _next_item_ 25000002
            }
    
        } elseif {$_next_item_ == 2463} {
            if {$i < $length} {
                #item 2462
                set current [ lindex $lines $i ]
                incr i
                set _next_item_ 25090001
            } else {
                #item 2466
                error "Unexpected end of block after $header"
                set _next_item_ 2516
            }
    
        } elseif {$_next_item_ == 25090001} {
            if {$current == "\{"} {
                #item 2472
                error "Unexpected '\{' in block after $header"
                set _next_item_ 2516
            } else {
                set _next_item_ 25090002
            }
    
        } elseif {$_next_item_ == 25090002} {
            if {$current == "\}"} {
                #item 2476
                lappend result \
                 [ list $header $fields ]
                set _next_item_ 2440
            } else {
                #item 2478
                lappend fields \
                 [ parse_g_line $header $current ]
                set _next_item_ 2463
            }
    
        } elseif {$_next_item_ == 25000002} {
            if {$current == "\}"} {
                #item 2507
                error "Unexpected '\}' after $header"
                set _next_item_ 2516
            } else {
                #item 2461
                error \
                "Expected '\{', got '$current' after $header"
                set _next_item_ 2516
            }
    
        } elseif {$_next_item_ == 2516} {
            return $result
    
        }
    }
}

proc parse_message_spec { line name } {
    #item 1593
    set spec [ lrange $line 1 end ]
    #item 1594
    return [ parse_argument $spec $name ]
}

proc previous_is_header { gdb vertex_id } {
    #item 1475
    set previous [ $gdb onecolumn {
    	select src
    	from links
    	where dst = :vertex_id
    	and ordinal = 1 } ]
    #item 1476
    set type [ $gdb onecolumn {
    	select type
    	from vertices
    	where vertex_id = :previous } ]
    #item 1477
    return [ expr { $type == "branch" } ]
}

proc print_cpp { header_filename fhandle functions ctrs dtrs methods slots header footer class_name language structure globals } {
    #item 204
    put_credits $fhandle
    #item 205
    set header_tail [ file tail $header_filename ]
    puts $fhandle "#include \"$header_tail\""
    #item 206
    puts $fhandle ""
    puts $fhandle $header
    #item 2808
    variable src_file
    set module_name [ take_module_name $src_file ]
    foreach function [ filter_functions $functions 0 static ] {
        #item 1146
        print_function $fhandle $function 1 "" $language
    }
    foreach function [ filter_functions $functions 1 static ] {
        #item 1149
        print_function $fhandle $function 1 "" $language
    }
    #item 1274
    puts $fhandle ""
    puts $fhandle $structure
    puts $fhandle ""
    puts $fhandle $globals
    
    init_current_file $fhandle
    gen_c_t::generate_cpp $module_name
    foreach function [ filter_functions $functions 1 static ] {
        #item 1152
        print_function $fhandle $function 0 "" $language
    }
    foreach function [ filter_functions $functions 0 static ] {
        #item 1170
        print_function $fhandle $function 0 "" $language
    }
    foreach function [ filter_functions $functions 0 public ] {
        #item 1155
        print_function $fhandle $function 0 "" $language
    }
    foreach method $ctrs {
        #item 1161
        print_function $fhandle $method 0 $class_name "cpp"
    }
    foreach method $dtrs {
        #item 1164
        print_function $fhandle $method 0 $class_name  "cpp"
    }
    foreach method $methods {
        #item 1167
        print_function $fhandle $method 0 $class_name "cpp"
    }
    foreach method $slots {
        #item 1254
        print_function $fhandle $method 0 $class_name "cpp"
    }
    #item 210
    puts $fhandle $footer
    #item 211
    puts $fhandle ""
}

proc print_function { fhandle function in_header class_name language } {
    #item 1035
    lassign $function diagram_id name signature body
    lassign $signature type prop_list parameters returns
    array set props $prop_list
    set inline $props(inline)
    #item 1174
    if {$language == "c"} {
        #item 1177
        set empty "void"
    } else {
        #item 1178
        set empty ""
    }
    #item 1063
    if {$type == "function"} {
        #item 1037
        set depth 0
        set static [ expr { $props(access) != "public" } ]
        set virtual 0
        set class ""
        set const 0
        set abstract 0
        set print_body [ expr !$in_header ]
        #item 1038
        print_function_kernel \
        $fhandle \
        $depth \
        $static \
        $virtual \
        $inline \
        $returns \
        $class \
        $name \
        $parameters \
        $props(const) \
        $abstract \
        $body \
        $print_body \
        $empty
    } else {
        #item 1046
        if {$in_header} {
            #item 1048
            set depth 1
            set static [ expr { $props(dispatch) == "static" } ]
            set virtual [ expr { $props(dispatch) == "virtual" } ]
            set class ""
            set abstract $props(abstract)
            #item 1051
            if {$inline} {
                #item 1054
                set print_body 1
            } else {
                #item 1050
                set print_body 0
            }
            #item 1059
            if {$type == "ctr"} {
                #item 1060
                set returns "explicit"
                set name $class_name
            } else {
                
            }
            #item 1068
            if {$type == "dtr"} {
                #item 1071
                set returns ""
                set name "~$class_name"
            } else {
                
            }
            #item 1038
            print_function_kernel \
            $fhandle \
            $depth \
            $static \
            $virtual \
            $inline \
            $returns \
            $class \
            $name \
            $parameters \
            $props(const) \
            $abstract \
            $body \
            $print_body \
            $empty
        } else {
            #item 1055
            set depth 0
            set static 0
            set virtual 0
            set class $class_name
            set abstract 0
            #item 1056
            if {($inline) || ($props(abstract))} {
                
            } else {
                #item 1070
                set print_body 1
                #item 1064
                if {$type == "ctr"} {
                    #item 1065
                    set returns ""
                    set name $class_name
                } else {
                    
                }
                #item 1068
                if {$type == "dtr"} {
                    #item 1071
                    set returns ""
                    set name "~$class_name"
                } else {
                    
                }
                #item 1038
                print_function_kernel \
                $fhandle \
                $depth \
                $static \
                $virtual \
                $inline \
                $returns \
                $class \
                $name \
                $parameters \
                $props(const) \
                $abstract \
                $body \
                $print_body \
                $empty
            }
        }
    }
}

proc print_function_kernel { fhandle depth static virtual inline returns class name parameters const abstract body print_body empty } {
    #item 515
    set result {}
    set line ""
    #item 513
    if {$static} {
        #item 514
        append line "static "
    } else {
        
    }
    #item 518
    if {$virtual} {
        #item 519
        append line "virtual "
    } else {
        
    }
    #item 522
    if {$inline} {
        #item 523
        append line "inline "
    } else {
        
    }
    #item 526
    append line "$returns "
    #item 533
    if {$class == ""} {
        
    } else {
        #item 535
        append line "$class\:\:"
    }
    #item 536
    append line "$name\("
    #item 588
    set param_count [ llength $parameters ]
    #item 527
    if {$param_count == 0} {
        #item 537
        append line "$empty\)"
    } else {
        #item 550
        lappend result $line
        #item 5400001
        set i 0
        while { 1 } {
            #item 5400002
            if {$i < $param_count} {
                
            } else {
                break
            }
            #item 543
            set parameter_info [ lindex $parameters $i ]
            set parameter [ lindex $parameter_info 0 ]
            #item 541
            set line "    $parameter"
            #item 544
            if {$i == $param_count - 1} {
                
            } else {
                #item 545
                append line ","
            }
            #item 552
            lappend result $line
            #item 5400003
            incr i
        }
        #item 542
        set line "\)"
    }
    #item 560
    if {$const} {
        #item 561
        append line " const"
    } else {
        
    }
    #item 564
    if {$abstract} {
        #item 565
        append line " = 0"
    } else {
        
    }
    #item 568
    if {$print_body} {
        #item 571
        append line " \{"
        #item 572
        lappend result $line
        foreach line $body {
            #item 582
            lappend result "    $line"
        }
        #item 585
        lappend result "\}"
    } else {
        #item 570
        append line ";"
        #item 573
        lappend result $line
    }
    #item 1021
    set space [ gen::make_indent $depth ]
    foreach line $result {
        #item 1022
        puts -nonewline $fhandle $space
        puts $fhandle $line
    }
    #item 1023
    puts $fhandle ""
}

proc print_header { filename fhandle functions ctrs dtrs methods signals slots header footer class copying class_name language structure globals } {
    #item 181
    put_credits $fhandle
    #item 171
    set guard [ gen_c::guard_name $filename ]
    #item 182
    puts $fhandle "#ifndef $guard"
    puts $fhandle "#define $guard"
    #item 183
    puts $fhandle ""
    puts $fhandle $header
    #item 2809
    variable src_file
    set module_name [ take_module_name $src_file ]
    #item 2810
    init_current_file $fhandle
    gen_c_t::generate_h $module_name
    #item 1273
    puts $fhandle ""
    puts $fhandle $structure
    #item 2358
    puts $fhandle ""
    puts $fhandle $globals
    foreach function [ filter_functions $functions 0 public ] {
        #item 186
        print_function $fhandle $function 1 "" $language
    }
    foreach function [ filter_functions $functions 1 public ] {
        #item 1109
        print_function $fhandle $function 1 "" $language
    }
    foreach function [ filter_functions $functions 1 public ] {
        #item 1112
        print_function $fhandle $function 0 "" $language
    }
    #item 1025
    if {$class == ""} {
        
    } else {
        #item 1131
        puts $fhandle $class
        #item 1185
        if {$copying} {
            
        } else {
            #item 1186
            noncopyable $fhandle $class_name
        }
        #item 1132
        print_methods $fhandle $ctrs public $class_name
        #item 1133
        print_methods $fhandle $ctrs protected $class_name
        #item 1135
        print_methods $fhandle $dtrs public $class_name
        #item 1134
        print_methods $fhandle $ctrs private $class_name
        #item 1255
        print_methods $fhandle $signals public $class_name "signals"
        #item 1245
        print_methods $fhandle $slots public $class_name "public slots"
        #item 1246
        print_methods $fhandle $slots protected $class_name "protected slots"
        #item 1247
        print_methods $fhandle $slots private $class_name "private slots"
        #item 1138
        print_methods $fhandle $methods public $class_name
        #item 1139
        print_methods $fhandle $methods protected $class_name
        #item 1140
        print_methods $fhandle $methods private $class_name
        #item 1024
        puts $fhandle "\};"
    }
    #item 187
    puts $fhandle $footer
    #item 188
    puts $fhandle "#endif"
    puts $fhandle ""
}

proc print_methods { fhandle functions access class_name {access_label ""} } {
    #item 1118
    set to_print [ filter_methods $functions $access ]
    #item 1119
    if {$to_print == ""} {
        
    } else {
        #item 1248
        if {$access_label == ""} {
            #item 1251
            set access_label $access
        } else {
            
        }
        #item 1120
        puts $fhandle "$access_label:"
        foreach method $to_print {
            #item 1124
            print_function $fhandle $method 1 $class_name "cpp"
        }
    }
}

proc print_sm_method { machine_name parameters bare_params message state_count } {
    #item 2349
    set lines {}
    #item 2328
    set callback "${machine_name}_callback"
    #item 2329
    lappend lines \
     "int ${machine_name}_${message}\($parameters\) \{"
    lappend lines "    $callback fun;"
    lappend lines "    int next;"
    #item 2331
    lappend lines \
     "    if \(machine == 0\) return 0;"
    #item 2332
    lappend lines \
     "    if \(*machine <= 0 || *machine > $state_count\) return 0;"
    #item 2345
    lappend lines \
     "    fun = ${machine_name}_${message}_methods\[*machine\];"
    lappend lines \
     "    if (!fun) return 0;"
    #item 2333
    set params_for_call \
     [ make_params_for_call $bare_params ]
    #item 2346
    lappend lines \
     "    next = fun\($params_for_call\);"
    lappend lines "    *machine = next;"
    #item 2330
    lappend lines "    return 1;"
    lappend lines "\}"
    #item 2350
    return $lines
}

proc put_credits { fhandle } {
    #item 180
    set version [ version_string ]
    puts $fhandle \
        "/* Autogenerated with DRAKON Editor $version */"
}

proc read_branch { gdb diagram_id ordinal } {
    #item 1620
    lassign [ $gdb eval {
    	select header_icon, first_icon
    	from branches
    	where diagram_id = :diagram_id
    	and ordinal = :ordinal 
    } ] header_icon first_icon
    #item 1622
    set receiving [ is_receive $gdb $first_icon ]
    #item 1621
    return [ list \
     ordinal $ordinal \
     header $header_icon \
     first $first_icon \
     receiving $receiving ]
}

proc receives_are_first { gdb diagram_id } {
    #item 1414
    set receives [ $gdb eval {
    	select vertex_id
    	from vertices
    	where diagram_id = :diagram_id
    	and type = 'action'
    	and text = 'RECEIVE' } ]
    foreach receive $receives {
        #item 1417
        if {[ previous_is_header $gdb $receive ]} {
            
        } else {
            #item 1428
            set name [ diagram_name $gdb $diagram_id ]
            #item 1430
            error "Diagram $name: a RECEIVE icon must be first in the branch."
        }
    }
}

proc receives_in_the_middle { gdb diagram_id } {
    #item 1438
    set max [ $gdb onecolumn {
    	select max(ordinal)
    	from branches
    	where diagram_id = :diagram_id } ]
    #item 1444
    set name [ diagram_name $gdb $diagram_id ]
    #item 1441
    if {[ starts_with_receive $gdb $diagram_id 1 ]} {
        #item 1445
        error "Diagram $name: a RECEIVE icon must not be placed on the first branch."
    } else {
        
    }
    #item 1466
    if {[ starts_with_receive $gdb $diagram_id $max ]} {
        #item 1469
        error "Diagram $name: a RECEIVE icon must not be placed on the last branch."
    } else {
        
    }
}

proc returns_void { gdb diagram_id } {
    #item 1379
    set params [ get_params $gdb $diagram_id ]
    #item 1393
    set lines [ split $params "\n" ]
    #item 1394
    set last [ lindex $lines end ]
    #item 1395
    set trimmed [ string trim $last ]
    #item 1397
    if {($trimmed == "returns void") || (!([ string match "returns *" $trimmed ]))} {
        
    } else {
        #item 1427
        set name [ diagram_name $gdb $diagram_id ]
        #item 1384
        error "Diagram $name is a state machine and must not return values."
    }
}

proc separate_globals { classes } {
    #item 2588
    set global_fields {}
    set nclasses {}
    foreach class $classes {
        #item 2581
        lassign $class name fields
        #item 2589
        if {$name == "globals"} {
            #item 2593
            if {$global_fields == {}} {
                
            } else {
                #item 2597
                error "More than one 'global' blocks"
                break
            }
            #item 2592
            set global_fields $fields
        } else {
            #item 2599
            lappend nclasses $class
        }
    }
    #item 2596
    return [ list \
     $global_fields $nclasses ]
}

proc set_diagram { gdb vertex_id diagram_id } {
    #item 1858
    $gdb eval {
    	update vertices
    	set diagram_id = :diagram_id
    	where vertex_id = :vertex_id
    }
}

proc sort_functions { functions language class_name } {
    #item 968
    set free_funs {}
    set ctrs {}
    set dtrs {}
    set methods {}
    set signals {}
    set slots {}
    foreach function $functions {
        #item 978
        lassign $function diagram_id name signature body
        lassign $signature type prop_list
        array set props $prop_list
        #item 980
        if {$type == "comment"} {
            
        } else {
            #item 983
            if {$type == "function"} {
                
            } else {
                #item 981
                if {$language == "c"} {
                    #item 986
                    error \
                    "$name: methods, constructors and destructors not supported by C language."
                    #item 988
                    error \
                    "$name: cannot have methods: class not defined."
                } else {
                    #item 987
                    if {$class_name == ""} {
                        #item 988
                        error \
                        "$name: cannot have methods: class not defined."
                    } else {
                        
                    }
                }
            }
            #item 9890001
            if {$type == "function"} {
                #item 999
                lappend free_funs $function
            } else {
                #item 9890002
                if {$type == "signal"} {
                    #item 1240
                    lappend signals $function
                } else {
                    #item 9890003
                    if {$type == "slot"} {
                        #item 1243
                        lappend slots $function
                    } else {
                        #item 9890004
                        if {$type == "method"} {
                            #item 1009
                            lappend methods $function
                        } else {
                            #item 9890005
                            if {$type == "ctr"} {
                                #item 1012
                                lappend ctrs $function
                            } else {
                                #item 9890006
                                if {$type == "dtr"} {
                                    
                                } else {
                                    #item 9890007
                                    error "Unexpected switch value: $type"
                                }
                                #item 1013
                                lappend dtrs $function
                            }
                        }
                    }
                }
            }
        }
    }
    #item 971
    return [ list \
    $free_funs \
    $ctrs \
    $dtrs \
    $methods \
    $signals \
    $slots ]
}

proc starts_with_receive { gdb diagram_id ordinal } {
    #item 1463
    set header [ $gdb onecolumn {
    	select header_icon
    	from branches
    	where diagram_id = :diagram_id
    	and ordinal = :ordinal } ]
    #item 1464
    set first [ gen::p.get_next $gdb $header 1 ]
    #item 1465
    return [ is_receive $gdb $first ]
}

proc state_fun_name { name text } {
    #item 1897
    set normal_name [ make_identifier $text ]
    #item 1898
    return "${name}_${normal_name}"
}

proc state_info_name { name text } {
    #item 1904
    set normal_name [ make_identifier $text ]
    #item 1905
    return "${name}_${normal_name}_State"
}

proc strip_comment { text } {
    #item 1547
    set comment_start [ string first "//" $text ]
    #item 1549
    if {$comment_start == -1} {
        #item 1552
        set wo_comment $text
    } else {
        #item 1548
        set before_comment $comment_start
        incr before_comment -1
        #item 1553
        set wo_comment [ string range $text 0 $before_comment ]
    }
    #item 1554
    return [ string trim $wo_comment ]
}

proc table_field_to_struct { field } {
    #item 2131
    set name [ get_value $field name ]
    set class [ get_value $field class ]
    set type [ get_value $field type ]
    #item 2135
    if {$type == "own"} {
        #item 2134
        set class "$class*"
    } else {
        
    }
    #item 2132
    return [ st::sfield $class $name "" ]
}

proc take_module_name { path } {
    #item 2799
    set tail [ file tail $path ]
    #item 2800
    set last [ string last "." $tail ]
    #item 2801
    if {$last == -1} {
        #item 2805
        set module_name $tail
    } else {
        #item 2804
        incr last -1
        set module_name [ string range $tail 0 $last ]
    }
    #item 2806
    return $module_name
}

proc update_returns { gdb functions } {
    #item 2298
    set result {}
    foreach fun $functions {
        #item 2302
        lassign $fun diagram_id name signature body
        lassign $signature type prop_list parameters returns
        #item 2303
        set original [ $gdb onecolumn {
        	select original
        	from diagrams
        	where diagram_id = :diagram_id
        } ]
        #item 2304
        if {$original == ""} {
            #item 2307
            lappend result $fun
        } else {
            #item 2308
            set returns "int"
            #item 2309
            set signature [ list $type $prop_list $parameters $returns ]
            set function [ list $diagram_id $name $signature $body ]
            #item 2310
            lappend result $function
        }
    }
    #item 2299
    return $result
}

proc zap_cleanups { gdb } {
    #item 2839
    set diagrams [ $gdb eval {
    	select diagram_id
    	from diagrams
    } ]
    foreach diagram_id $diagrams {
        #item 2842
        if {[sma::is_from_machine $gdb $diagram_id]} {
            #item 2846
            set name [ $gdb onecolumn {
            	select name
            	from diagrams
            	where diagram_id = :diagram_id
            } ]
            #item 2845
            if {[string match "*_CleanUp" $name]} {
                #item 2847
                $gdb eval {
                	delete from diagrams
                	where diagram_id = :diagram_id
                }
            } else {
                
            }
        } else {
            
        }
    }
}

}
