home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1998 October
/
PCWorld_1998-10_cd.bin
/
software
/
prehled
/
komix
/
DATA.Z
/
cppgentor.tcl
< prev
next >
Wrap
Text File
|
1997-12-01
|
14KB
|
549 lines
#---------------------------------------------------------------------------
#
# Copyright (c) 1997 by Cayenne Software, 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 Cayenne Software, Inc.
#
#---------------------------------------------------------------------------
#
# File : cppgentor.tcl
# Author :
# Original date : November 1997
# Description : Classes for code generation
#
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
# File: @(#)cppfilehan.tcl /main/titanic/2
#---------------------------------------------------------------------------
# Start user added include file section
# End user added include file section
require "filehandle.tcl"
Class CppFileHandler : {FileHandler} {
constructor
method destructor
method promotor
method getSpecialFiles
method getFileTypes
method getMakefileName
attribute hdrType
attribute cppType
}
constructor CppFileHandler {class this} {
set this [FileHandler::constructor $class $this]
# Start constructor user section
$this promotor
# End constructor user section
return $this
}
method CppFileHandler::destructor {this} {
# Start destructor user section
# End destructor user section
$this FileHandler::destructor
}
method CppFileHandler::promotor {this} {
# Should get this information from the repository
$this hdrType "h++"
$this cppType "c++"
}
method CppFileHandler::getSpecialFiles {this} {
set list [List new]
$list append [$this getMakefileName]
return $list
}
method CppFileHandler::getFileTypes {this} {
set list [List new]
$list append [$this hdrType]
$list append [$this cppType]
return $list
}
method CppFileHandler::getMakefileName {this} {
return "makefile"
}
# Do not delete this line -- regeneration end marker
#---------------------------------------------------------------------------
# File: @(#)cppconstan.tcl /main/titanic/2
#---------------------------------------------------------------------------
# Start user added include file section
# End user added include file section
Class CppConstants : {Object} {
constructor
method destructor
}
global CppConstants::startInclude
set CppConstants::startInclude "Start user added include file section"
global CppConstants::endInclude
set CppConstants::endInclude "End user added include file section"
global CppConstants::startDtor
set CppConstants::startDtor "Start destructor user section"
global CppConstants::endDtor
set CppConstants::endDtor "End destructor user section"
global CppConstants::startCtor
set CppConstants::startCtor "Start constructor user section"
global CppConstants::endCtor
set CppConstants::endCtor "End constructor user section"
global CppConstants::regenEnd
set CppConstants::regenEnd "Do not delete this line -- regeneration end marker"
global CppConstants::obsoleteCode
set CppConstants::obsoleteCode "OBSOLETE_CODE"
global CppConstants::oldCode
set CppConstants::oldCode "OLDCODE"
constructor CppConstants {class this name} {
set this [Object::constructor $class $this $name]
# Start constructor user section
# End constructor user section
return $this
}
method CppConstants::destructor {this} {
# Start destructor user section
# End destructor user section
}
# Do not delete this line -- regeneration end marker
#---------------------------------------------------------------------------
# File: @(#)cppregener.tcl /main/titanic/9
#---------------------------------------------------------------------------
# Start user added include file section
# End user added include file section
require "regenerato.tcl"
Class CppRegenerator : {Regenerator} {
constructor
method destructor
method checkFile
method processUserIncs
method processCtorDtor
method processUserDefMeth
method regenerate
}
constructor CppRegenerator {class this} {
set this [Regenerator::constructor $class $this]
# Start constructor user section
# End constructor user section
return $this
}
method CppRegenerator::destructor {this} {
# Start destructor user section
# End destructor user section
$this Regenerator::destructor
}
method CppRegenerator::checkFile {this fileName fileDesc fileType} {
set brace 0
seek $fileDesc 0
set line [gets $fileDesc]
set obsoleteTxt "#ifdef ${CppConstants::obsoleteCode}"
set oldTxt "#ifdef ${CppConstants::oldCode}"
while {![eof $fileDesc]} {
if {[regexp "^$oldTxt" $line] || [regexp "^$obsoleteTxt" $line] } {
m4_error $E_CONTAINSOLD $fileName ${CppConstants::obsoleteCode} ${CppConstants::oldCode}
return 0
}
if {(![regexp {^\};$} $line]) || ($fileType != "hdr") } {
if {[regexp {^\}.+} $line] || [regexp {^\{.+} $line]} {
m4_error $E_UNMATCHBRACES $fileName
return 0
}
}
if {[regexp {^\{$} $line] } {
incr brace
}
if {[regexp {^\}$} $line] } {
if {$brace >= 1} {
incr brace -1
} else {
m4_error $E_UNMATCHBRACES $fileName
return 0
}
}
set line [gets $fileDesc]
}
if {$brace != 0} {
m4_error $E_UNMATCHBRACES $fileName
return 0
}
return 1
}
method CppRegenerator::processUserIncs {this class fileDesc fileType} {
set sect [$class getIncludeSect $fileType]
set includeLine 0
seek $fileDesc 0
set line [gets $fileDesc]
while {![eof $fileDesc]} {
if [regexp "^// ${CppConstants::endInclude}\$" $line] {
break
}
if {$includeLine} {
$sect append $line
$sect append "\n"
}
if [regexp "^// ${CppConstants::startInclude}\$" $line] {
set includeLine 1
}
set line [gets $fileDesc]
}
if [eof $fileDesc] {
seek $fileDesc 0
return 0
}
return 1
}
method CppRegenerator::processCtorDtor {this class fileDesc fileType} {
if { $fileType == "hdr" } {
return
}
if {![$class isA CppClass]} {
return
}
set line [gets $fileDesc]
set stage 0
set ctorSect ""
set dtorSect ""
# Find constructor and destructor (if there are any).
[$class featureSet] foreach feature {
if [$feature isA CppConstructor] {
set ctorSect [CppRegen new $feature]
}
if [$feature isA CppDestructor] {
set dtorSect [CppRegen new $feature]
}
}
set obsolete 0
if {$ctorSect == ""} {
set obsolete 1
set ctorSect [$class getObsoleteCode $fileType]
}
while {![eof $fileDesc]} {
if {[regexp "// ${CppConstants::endDtor}\$" $line] &&
($stage == 3)} {
break
}
if {$stage == 3} {
if {$dtorSect != ""} {
$dtorSect append $line
$dtorSect append "\n"
}
}
if {[regexp "// ${CppConstants::startDtor}\$" $line]} {
set stage 3
}
if {[regexp "// ${CppConstants::endCtor}\$" $line] &&
($stage == 1)} {
if {$obsolete} {
$ctorSect append "\}\n"
}
set stage 2
}
if {$stage == 1} {
if {$ctorSect != ""} {
$ctorSect append $line
$ctorSect append "\n"
}
}
if {[regexp "// ${CppConstants::startCtor}\$" $line] &&
($stage == 0)} {
if {$obsolete} {
$ctorSect append "void obsoleteUserSectOfCtor()\n"
$ctorSect append "\{\n"
}
set stage 1
}
set line [gets $fileDesc]
}
if [eof $fileDesc] {
lseek $fileDesc 0 start
}
}
method CppRegenerator::processUserDefMeth {this class fileDesc fileType} {
set exp_method {^(.+ )?([&*]*)[^: ]+::([^\(]+)\(([^\)]*)\).*$}
set line [gets $fileDesc]
set sect ""
while {(![eof $fileDesc]) &&
(![regexp "^// ${CppConstants::regenEnd}" $line])} {
if [regexp $exp_method $line dummy type modifiers methodName params] {
set signatureLine $line
set signature ""
foreach param [split $params ","] {
if [regexp {^(const )?([^*&]+)(&)?(\*)?( [^ ]+)$} \
[string trim $param] dummy constDef planeType ref ptr name] {
set signature "${signature}${planeType}${ptr}|"
} else {
set signature "${signature}|"
}
}
set foundFeature ""
if [$class isA CppClass] {
[$class featureSet] foreach feature {
if {($methodName == [$feature getName]) &&
[$feature isA CppUserMethod] &&
[[$feature regenSet] empty]} {
set featureSig ""
[$feature paramSet] foreach param {
set ptype [[$param type] getTypeName "" $class]
if [regexp {^(const )?([^*&]+)(&)?(\*)?$} $ptype dummy constDef planeType ref ptr] {
if [[$param type] isArray] {
set constDef "const "
set ptr "*"
}
if [[$param type] isPointer] {
set ptr "*"
}
set featureSig "${featureSig}${planeType}${ptr}|"
} else {
set featureSig "${featureSig}|"
}
}
if {$featureSig == $signature} {
set foundFeature $feature
break
}
}
}
}
set userBody [TextSection new]
set line [gets $fileDesc]
if {![regexp "^\{" $line]} {
m4_error $E_SYNTAX "Unexpected '$line'"
}
set line [gets $fileDesc]
while {(![eof $fileDesc]) && (![regexp "^\}" $line])} {
$userBody append "$line\n"
set line [gets $fileDesc]
}
if {$foundFeature == ""} {
set obsoleteName($signature) $methodName
set obsoleteCode($signature) $userBody
set obsoleteLine($signature) $signatureLine
} else {
set mUserBody [CppRegen new $foundFeature]
$mUserBody appendSect $userBody
}
}
set line [gets $fileDesc]
}
if [array exists obsoleteName] {
foreach signature [array names obsoleteName] {
[$class featureSet] foreach feature {
if {[$feature getName] == $obsoleteName($signature) &&
[[$feature regenSet] empty]} {
if {$fileType == "hdr"} {
m4_warning $W_GENOCODE ${CppConstants::oldCode} [$class hdrFileName]
} else {
m4_warning $W_GENOCODE ${CppConstants::oldCode} [$class cppFileName]
}
set mUserBody [CppRegen new $feature]
$mUserBody append "#ifdef ${CppConstants::oldCode}\n"
$mUserBody appendSect $obsoleteCode($signature)
$mUserBody append "#else // ${CppConstants::oldCode}\n"
$mUserBody indent +
$mUserBody append "// insert new implementation here\n"
$mUserBody indent -
$mUserBody append "#endif // ${CppConstants::oldCode}\n"
unset obsoleteName($signature)
unset obsoleteCode($signature)
unset obsoleteLine($signature)
break
}
}
}
}
if [array exists obsoleteName] {
foreach signature [array names obsoleteName] {
set sect [$class getObsoleteCode $fileType]
$sect append $obsoleteLine($signature)
$sect append "\n\{\n"
$sect appendSect $obsoleteCode($signature)
$sect append "\}\n\n"
}
}
}
method CppRegenerator::regenerate {this class fileDesc fileType} {
if {$fileType == "hdr"} {
set fileName [$class hdrFileName]
} else {
set fileName [$class cppFileName]
}
if [$this checkFile $fileName $fileDesc $fileType] {
set hasUserIncs [$this processUserIncs $class $fileDesc $fileType]
if {(!$hasUserIncs) && $fileType == "hdr"} {
# In header files generated by pre-7.1.1 there can't be user-defined
# methods in the header file
m4_warning $W_UPGRADE [$class name]
} else {
$this processCtorDtor $class $fileDesc $fileType
$this processUserDefMeth $class $fileDesc $fileType
}
return 1
}
return 0
}
# Do not delete this line -- regeneration end marker
#---------------------------------------------------------------------------
# File: @(#)cppgenerat.tcl /main/titanic/7
#---------------------------------------------------------------------------
# Start user added include file section
global dontCallMakeMake
set dontCallMakeMake 1
require makemake.tcl
# End user added include file section
require "generator.tcl"
Class CppGenerator : {Generator} {
constructor
method destructor
method promotor
method generate
method check
method generateSpecialFiles
attribute fileHandler
}
constructor CppGenerator {class this} {
set this [Generator::constructor $class $this]
# Start constructor user section
$this promotor
# End constructor user section
return $this
}
method CppGenerator::destructor {this} {
# Start destructor user section
# End destructor user section
$this Generator::destructor
}
method CppGenerator::promotor {this} {
$this fileHandler [CppFileHandler new]
}
method CppGenerator::generate {this classList} {
set ok 1
set typeToClassDict [Dictionary new]
set tgtModel [CppModel new]
set regen [CppRegenerator new]
set ooplToTarget [Dictionary new]
puts "Generating target language model..."
$classList foreach cl {
set tclass [$cl generate $tgtModel]
$ooplToTarget set $cl $tclass
}
$tgtModel setFileNameParams [$this fileHandler]
puts "(Re)generating source files..."
$classList foreach cl {
set tclass [$ooplToTarget set $cl]
set fileDesc [[$this fileHandler] \
openFile $cl [[$this fileHandler] hdrType]]
if {$fileDesc != ""} {
if {![$regen regenerate $tclass $fileDesc "hdr"]} {
set ok 0
}
[$this fileHandler] closeFile $fileDesc
}
set fileDesc [[$this fileHandler] \
openFile $cl [[$this fileHandler] cppType]]
if {$fileDesc != ""} {
if {![$regen regenerate $tclass $fileDesc "cpp"]} {
set ok 0
}
[$this fileHandler] closeFile $fileDesc
}
}
if {$ok} {
$tgtModel generate $typeToClassDict
}
return $typeToClassDict
}
method CppGenerator::check {this classList} {
$classList foreach class {
$class check
}
}
method CppGenerator::generateSpecialFiles {this fileList} {
foreach file $fileList {
if { $file == "makefile" } {
makemake
}
}
}
# Do not delete this line -- regeneration end marker