home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1998 October
/
PCWorld_1998-10_cd.bin
/
software
/
prehled
/
komix
/
DATA.Z
/
ne_regen.tcl
< prev
next >
Wrap
Text File
|
1997-10-24
|
9KB
|
317 lines
#---------------------------------------------------------------------------
#
# Copyright (c) 1994-1995 by Cadre Technologies Inc.
#
# This software is furnished under a license and may be used only in
# accordance with the terms of such license and with the inclusion of
# the above copyright notice. This software or any other copies thereof
# may not be provided or otherwise made available to any other person.
# No title to and ownership of the software is hereby transferred.
#
# The information in this software is subject to change without notice
# and should not be construed as a commitment by Cadre Technologies Inc.
#
#---------------------------------------------------------------------------
#
# File : @(#)ne_regen.tcl /main/titanic/1
# 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} {
process_start_end_piece $fd "" \
$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
if {$st_msg != ""} {
set line [gets $fd]
while {![eof $fd] && ![string match *$st_msg $line]} {
set line [gets $fd]
}
set found [string match *$st_msg $line]
} else {
set found 1
}
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"
}