home *** CD-ROM | disk | FTP | other *** search
- #---------------------------------------------------------------------------
- #
- # Copyright (c) 1994-1995 by Cadre Technologies Inc.
- #
- # This software is furnished under a license and may be used only in
- # accordance with the terms of such license and with the inclusion of
- # the above copyright notice. This software or any other copies thereof
- # may not be provided or otherwise made available to any other person.
- # No title to and ownership of the software is hereby transferred.
- #
- # The information in this software is subject to change without notice
- # and should not be construed as a commitment by Cadre Technologies Inc.
- #
- #---------------------------------------------------------------------------
- #
- # File : @(#)ne_regen.tcl 1.4
- # Original date : 17-12-1994
- # Description : Regeneration code
- # regenerates user added method bodies
- # regenerates start-end bounded pieces of code
- #
- #---------------------------------------------------------------------------
- #
-
- proc prepare_regeneration {class} {
- global re_user_includes re_ctor re_found_ctor re_dtor re_user_source
- global re_split
- set re_user_includes ""
- set re_ctor ""
- set re_found_ctor 0
- set re_dtor ""
- set re_user_source ""
- catch {unset re_split}
-
- class2tgtfiles $class src_file h_file
- if {![fstorage::exists $src_file]} {
- return
- }
- if [catch {set fd [fstorage::open $src_file r]}] {
- return
- }
-
- check_code $class $fd
-
- # include piece
- seek $fd 0
- global START_INCLUDE_MESSAGE END_INCLUDE_MESSAGE
- process_start_end_piece $fd $START_INCLUDE_MESSAGE \
- $END_INCLUDE_MESSAGE re_user_includes
- # constructor piece
- # expect constructor/destructor after include part
- set pos [tell $fd]
- global START_CTOR_MESSAGE END_CTOR_MESSAGE
- set re_found_ctor [process_start_end_piece $fd $START_CTOR_MESSAGE \
- $END_CTOR_MESSAGE re_ctor]
- # destructor piece
- # do NOT expect it after the constructor
- # so reset to pos
- seek $fd $pos
- global START_DTOR_MESSAGE END_DTOR_MESSAGE
- process_start_end_piece $fd $START_DTOR_MESSAGE \
- $END_DTOR_MESSAGE re_dtor
-
- seek $fd 0
- set last_line [process_user_added_methods $fd]
-
- # user source piece
- # expect it after user added methods
- # so reset to the last line if appropriate
- global START_SOURCE_MESSAGE END_SOURCE_MESSAGE
- if {$last_line == $START_SOURCE_MESSAGE} {
- set back [expr {[string length $START_SOURCE_MESSAGE] + 1}]
- seek $fd -$back current
- process_start_end_piece $fd $START_SOURCE_MESSAGE \
- $END_SOURCE_MESSAGE re_user_source
- }
-
- fstorage::close $fd
- }
-
- proc print_regen_code {} {
- global re_user_includes re_ctor re_dtor re_split
- if {![info exists re_split]} {
- puts stdout "####NO REGEN CODE####"
- return
- }
- puts stdout "####START REGEN CODE####"
- foreach el [array names re_split] {
- set len [llength $re_split($el)]
- set i 0
- while {$i < $len} {
- puts stdout "FUNCTION ${el} [lindex $re_split($el) $i]"
- incr i
- puts stdout [lindex $re_split($el) $i]
- incr i
- puts stdout "END FUNCTION"
- }
- }
- puts stdout "####END REGEN CODE####"
- }
-
- # check for OLDCODE
- # check for OBSOLETE CODE
- # check for non matching FUNCTION and END FUNCTION pairs
-
- proc check_code {class fd} {
- set line [gets $fd]
- set in_function 0
- while {![eof $fd] && $line != "\{ START OLDCODE" && \
- $line != "\{ START OBSOLETE_CODE" } {
- if {[regexp {^FUNCTION} $line]} {
- if {$in_function} {
- error [function_delim_error $class $line]\
- "" ERR_REGEN
- } else {
- set in_function 1
- }
- }
- if {[regexp {^END FUNCTION} $line]} {
- if {!$in_function} {
- error [function_delim_error $class $line]\
- "" ERR_REGEN
- } else {
- set in_function 0
- }
- }
- set line [gets $fd]
- }
- if {$line == "\{ START OLDCODE" || $line == "\{ START OBSOLETE_CODE"} {
- error [oldcode_error_msg $class $line] "" ERR_REGEN
- }
- }
-
- proc process_start_end_piece {fd st_msg end_msg result} {
- upvar $result lresult
- set lresult ""
- set found 0
- set line [gets $fd]
- while {![eof $fd] && ![string match *$st_msg $line]} {
- set line [gets $fd]
- }
- set found [string match *$st_msg $line]
- set line [gets $fd]
- while {![eof $fd] && ![string match *$end_msg $line]} {
- append lresult "$line\n"
- set line [gets $fd]
- }
- return $found
- }
-
- # Fill the global array 're_split' with all the method bodies.
- # The key is the method name.
- # The contents is a list of method type and method contents.
- # For each overloaded method this list is extended with
- # another type and contents. The order of this list is the file order.
-
- proc process_user_added_methods {fd} {
- global re_split
-
- while {![eof $fd]} {
- set line [gets $fd]
- if {$line == $REGEN_END || $line == $START_SOURCE_MESSAGE} {
- break
- }
- set exp_method {^FUNCTION .*::([^\(][^\(]*)(.*[\):])}
- if [regexp $exp_method $line dummy method type] {
- set result ""
-
- # handle possible ':'
- set tr_type [string trimright $type :]
- if {$tr_type != $type} {
- # also remove whitespace from type
- set type [string trimright $tr_type]
- append result " :"
- }
-
- # handle possible 'RETURNING CHAR(*)'
- set ret_pos [string last RETURNING $type]
- if {$ret_pos != -1} {
- incr ret_pos -1
- set type [string range $type 0 $ret_pos]
- set type [string trimright $type]
- }
-
- append result "\n"
- set exp_func_end {^END FUNCTION$}
- set line [gets $fd]
- while {![eof $fd] && ![regexp $exp_func_end $line]} {
- append result "$line\n"
- set line [gets $fd]
- }
- if [info exist re_split($method)] {
- lappend re_split($method) $type
- lappend re_split($method) $result
- } else {
- set re_split($method) [list $type $result]
- }
- }
- }
- return $line
- }
-
- # provide a method body; a default message or a previously edited one
- # look in global array 're_split' for user added method bodies.
-
- proc get_method_body {method_name method_type section} {
- global re_split
- if {![info exists re_split($method_name)]} {
- # no match, provide the default message
- $section indent +
- expand_text $section {
-
- -- Implement this function!
- --
- }
- $section indent -
- return
- }
-
- set avail [lsearch $re_split($method_name) $method_type]
- if {$avail != -1} {
- # full match, name and type
-
- lvarpop re_split($method_name) $avail
- expand_text $section {
- ~[lvarpop re_split($method_name) $avail]}
- } else {
- # method name matched, method type not
- # probabely this is the one, but the
- # parameters have changed
- # just pick the first one of the list
-
- global ne_error_state
- if {! $ne_error_state } {
- puts stdout "WARNING: generated OLDCODE section"
- }
-
- lvarpop re_split($method_name)
- expand_text $section {
-
- { START OLDCODE
- ~[lvarpop re_split($method_name)
- ]}
- -- Implement this function!
- --
- }
- }
- if {[llength $re_split($method_name)] == 0} {
- unset re_split($method_name)
- }
- }
-
- proc oldcode_error_msg {class line} {
- class2tgtfiles $class src_file h_file
- set msg "ERROR: Generation for class '[$class getName]' failed:\n"
- append msg " file '$src_file' still contains '$line' line"
- return $msg
- }
-
- proc function_delim_error {class line} {
- class2tgtfiles $class src_file h_file
- set msg "ERROR: Generation for class '[$class getName]' failed:\n"
- append msg " FUNCTION and END FUNCTION pairs do not match\n"
- if {$line != ""} {
- append msg " code regeneration failed for line '$line'\n"
- }
- return $msg
- }
-
- proc regen_unset {method_name method_type} {
- global re_split
- if {![info exists re_split($method_name)]} {
- return
- }
-
- set avail [lsearch $re_split($method_name) $method_type]
- if {$avail != -1} {
- set x [lvarpop re_split($method_name) $avail]
- lvarpop re_split($method_name) $avail
- } else {
- # just pick the first one
- lvarpop re_split($method_name)
- lvarpop re_split($method_name)
- }
- if {[llength $re_split($method_name)] == 0} {
- unset re_split($method_name)
- }
- }
-
- proc append_obsolete_code {class} {
- global re_split
- if {! [info exists re_split]} {
- return
- }
- if {[array names re_split] == ""} {
- return
- }
- global ne_error_state
- if {! $ne_error_state } {
- puts "WARNING: appending obsolete code section"
- }
- set sect $ne_sections(c_impl_no_regen_sect)
- $sect append "\n\{ START OBSOLETE_CODE\n"
-
- foreach el [array names re_split] {
- while {[llength $re_split($el)] != 0} {
- set nmfc "[$class getName]::$el[lvarpop re_split($el)]"
- $sect append "Function $nmfc:\n"
- $sect append "[lvarpop re_split($el)]\n"
- }
- }
- $sect append "\}\n"
- }
-
-