home *** CD-ROM | disk | FTP | other *** search
Wrap
#--------------------------------------------------------------------------- # # 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 : delphigtor.tcl # Author : # Original date : May 1997 # Description : Classes for code generation # #--------------------------------------------------------------------------- #--------------------------------------------------------------------------- # File: @(#)dpfilehand.tcl /main/hindenburg/3 #--------------------------------------------------------------------------- # Start user added include file section # End user added include file section require "filehandle.tcl" Class DPFileHandler : {FileHandler} { constructor method destructor method getFileName method getSpecialFiles method getFileTypes method getProjectFileName } global DPFileHandler::DPRType set DPFileHandler::DPRType "dpr" global DPFileHandler::PASType set DPFileHandler::PASType "pas" global DPFileHandler::DFMType set DPFileHandler::DFMType "txt" constructor DPFileHandler {class this} { set this [FileHandler::constructor $class $this] # Start constructor user section # End constructor user section return $this } method DPFileHandler::destructor {this} { # Start destructor user section # End destructor user section $this FileHandler::destructor } method DPFileHandler::getFileName {this class fileType} { return "[$class getUnitName].$fileType" } method DPFileHandler::getSpecialFiles {this} { set list [List new] $list append [$this getProjectFileName] return $list } method DPFileHandler::getFileTypes {this} { set list [List new] $list append ${DPFileHandler::DPRType} $list append ${DPFileHandler::PASType} $list append ${DPFileHandler::DFMType} return $list } method DPFileHandler::getProjectFileName {this} { return "[getCurrentSystemName].${DPFileHandler::DPRType}" } # Do not delete this line -- regeneration end marker #--------------------------------------------------------------------------- # File: @(#)dpgenerato.tcl /main/hindenburg/9 #--------------------------------------------------------------------------- # Start user added include file section # End user added include file section require "generator.tcl" Class DPGenerator : {Generator} { constructor method destructor method generateProjectSections method generateProjectFile method generate method generateSpecialFiles attribute fileHandler attribute ooplModel } constructor DPGenerator {class this} { set this [Generator::constructor $class $this] # Start constructor user section $this fileHandler [DPFileHandler new] # End constructor user section return $this } method DPGenerator::destructor {this} { # Start destructor user section # End destructor user section $this Generator::destructor } method DPGenerator::generateProjectSections {this uses code} { set startupForm "" set nrStartupForms 0 set systemUsesList {} set standardUsesList {} set formsList {} set newUsesList {} foreach class [[$this ooplModel] ooplClassSet] { if {[$class isExternal] || [$class baseType] == "TComponent"} { continue } if {[$class getPropertyValue "is_startup"] == 1} { if {[$class baseType] == "TForm"} { if {$nrStartupForms != 0} { m4_error $E_DOUBLESTARTUP [$class getFormVarName] [$startupForm getFormVarName] } else { incr nrStartupForms set startupForm $class } } else { m4_warning $W_CANTBESTARTUP [$class getName] } } if {[$class baseType] == "TForm"} { set formsList [linsert $formsList 0 $class] } set libunit [$class getPropertyValue "libunit"] if {$libunit != "None" && $libunit != ""} { if {$libunit == "Other"} { set name [$class getPropertyValue "userlib"] } else { set name $libunit } if {[lsearch -exact $systemUsesList $name] == -1} { set systemUsesList [linsert $systemUsesList 0 $name] } } else { # set name [$class getUnitName] if {[lsearch -exact $standardUsesList $class] == -1} { set standardUsesList [linsert $standardUsesList 0 $class] } } } set first 1 foreach name $systemUsesList { if {$first} { set first 0 } else { $uses append ",\n" } $uses append "${name}" set newUsesList [linsert $newUsesList 0 $name] } foreach class $standardUsesList { if {$first} { set first 0 } else { $uses append ",\n" } $uses append "[$class getUnitName] in '[$class getUnitName].pas'" set newUsesList [linsert $newUsesList 0 [$class getUnitName]] if {[$class baseType] == "TForm"} { $uses append " \{[$class getFormVarName]\}" } } if {[$uses contents] != ""} { $uses append "\n" } if {$formsList != "" && $nrStartupForms == 0} { set startupForm [lindex $formsList 0] m4_warning $W_NOSTARTUP [$startupForm getFormVarName] } $code indent + if {$startupForm != ""} { $code append "Application.CreateForm([$startupForm getFormTypeName], [$startupForm getFormVarName]);\n" } # foreach form $formsList { # if {[$form getFormVarName] != [$startupForm getFormVarName]} { # $code append "Application.CreateForm([$form getFormTypeName], [$form getFormVarName]); ${DPCookie::genProjectCode}\n" # } # } $code indent - return $newUsesList } method DPGenerator::generateProjectFile {this fileName uses code newUsesList} { set oldProject [TextSection new] set newProject [TextSection new] set cc [ClientContext::global] set projectName [getCurrentSystemName] set dprType ${DPFileHandler::DPRType} set genUsesList {} if {[catch {set fileDesc [fstorage::open [[$this fileHandler] getProjectFileName] r]}]} { # Search for customization file $oldProject append [$cc getCustomFileContents "default" "dpr" etc] } else { # Read existing file while {![eof $fileDesc]} { set line [gets $fileDesc] $oldProject append "$line\n" } fstorage::close $fileDesc } # Check for valid contents and grab sections # if {![regexp {[ ]*(program|library)[ ]*([^;]*);.((.*)uses.([^;]*);.)?(.*)begin.(.*)} [$oldProject contents] total prjType prjName dummy1 grab1 usesBody grab2 remain]} { m4_error $E_PRJCONTENTS return $newProject } if {![regexp {(.*)[ ]*end\..*(// Do not delete this block -- regeneration marker -- start)(.*)(// Do not delete this block -- regeneration marker -- end)} $remain total grabCode dummy1 genuses dummy2]} { m4_error $E_PRJCONTENTS return $newProject } # Grab generated uses in old file # set tempList [split $genuses "\n"] foreach line $tempList { if {[regexp {^[ ]*//[ ]*([^ ]+)$} $line total name]} { set genUsesList [linsert $genUsesList 0 $name] } } # Project type and name # if {$prjName == "<default>"} { set prjName $projectName } $newProject append "${prjType} ${prjName};" $newProject append $grab1 # Uses # set usesList [split $usesBody "\n"] if {$uses != ""} { $newProject append "\nuses\n" $newProject indent + set first 1 set oldremain "" foreach line $usesList { if {[regexp {^[ ]*(([^ ,;]+)([ ]+in[ ]+[^ ,;]+)?)([,;])?([ ]*.*)$} $line total name unitname filename dummy remain]} { if {[lsearch -exact $genUsesList $unitname] == -1 && [lsearch -exact $newUsesList $unitname] == -1} { if {$first} { set first 0 } else { $newProject append "," $newProject append "${oldremain}\n" } set oldremain $remain $newProject append "${name}" } } } if {!$first} { if {$uses != ""} { $newProject append "," } $newProject append "${oldremain}\n" } $newProject appendSect $uses $newProject append ";\n" $newProject indent - } $newProject append $grab2 # Code # $newProject append "begin\n" if {[regexp {(.*)[ ]*Application\.Run;.(.*)} $grabCode total codeBody1 codeBody2]} { set codeList [split $codeBody1 "\n"] foreach line $codeList { if {![regexp "Application.CreateForm" $line]} { if {![regexp {^[ ]*$} $line]} { $newProject append "${line}\n" } } } $newProject appendSect $code $newProject indent + $newProject append "Application.Run;\n" $newProject indent - $newProject append $codeBody2 } $newProject append "end.\n\n\n" $newProject append "${DPCookie::genProjectStart}\n" foreach name $newUsesList { $newProject append "// ${name}\n" } $newProject append "${DPCookie::genProjectEnd}\n" return $newProject } method DPGenerator::generate {this classList} { set typeToClassDictionary [Dictionary new] set project [DPProject new] set regenerator [DPRegenerator new [$this fileHandler]] set pasType ${DPFileHandler::PASType} set formType ${DPFileHandler::DFMType} $classList foreach class { # Generation # $class generate $project # Regeneration # # Class file set fileDesc [[$this fileHandler] openFile $class $pasType] if {$fileDesc != ""} { $regenerator regenerate $project $class $fileDesc [$this fileHandler] closeFile $fileDesc } # Form file if {[$class baseType] == "TForm"} { set formfileDesc [[$this fileHandler] openFile $class $formType] if {$formfileDesc != ""} { $regenerator regenerateForm $project $class $formfileDesc [$this fileHandler] closeFile $formfileDesc } } $typeToClassDictionary set $class [Dictionary new] } $project generate $typeToClassDictionary return $typeToClassDictionary } method DPGenerator::generateSpecialFiles {this fileList} { $fileList foreach specialFile { set fileName [[$this fileHandler] getProjectFileName] set project [TextSection new] set usesSection [TextSection new] set codeSection [TextSection new] set newUsesList {} set newUsesList [$this generateProjectSections $usesSection $codeSection] m4_message $M_CREATINGSPEC $fileName $project appendSect [$this generateProjectFile $fileName $usesSection $codeSection $newUsesList] if {[$project contents] != ""} { [$this fileHandler] writeSectionToNamedFile $project $fileName } } } # Do not delete this line -- regeneration end marker #--------------------------------------------------------------------------- # File: @(#)dpregenera.tcl /main/hindenburg/11 #--------------------------------------------------------------------------- # Start user added include file section # End user added include file section require "regenerato.tcl" Class DPRegenerator : {Regenerator} { constructor method destructor method sanityCheck method addUserCodeToMethod method grabMethodBody method grabUserIncludes method processCodeDef method grabComponentProperties method regenerateForm method regenerate attribute fileHandler } constructor DPRegenerator {class this fileHandler} { set this [Regenerator::constructor $class $this] $this fileHandler $fileHandler # Start constructor user section # End constructor user section return $this } method DPRegenerator::destructor {this} { # Start destructor user section # End destructor user section $this Regenerator::destructor } method DPRegenerator::sanityCheck {this fileDesc} { while {![eof $fileDesc]} { set line [gets $fileDesc] if {[string match *${DPCookie::obsoleteCode} $line]} { seek $fileDesc 0 return 1 } if {[regexp {(IFDEF OLDCODE)} $line]} { seek $fileDesc 0 return 2 } } seek $fileDesc 0 return 0 } method DPRegenerator::addUserCodeToMethod {this project class line userTypes userCode} { set dpclass [$project getUnit [$class getName]] set methodExpr {^[ ]*(class)?[ ]*(procedure|function|constructor|destructor)[ ]*([^.]*)\.([^(;:]*)(\(([^)]*)\))?[ ]*(:[ ]*([^ ]*))?;} regexp $methodExpr $line total classType methodType classname name dummy1 params dummy2 returnvalue if {$dpclass == ""} { return } # Find procedure set proc [$dpclass getUsermethod [string tolower $name]] if {$proc == ""} { set proc [$dpclass getEvent [string tolower $name]] } if {$proc == ""} { if {[$dpclass destructr] != ""} { if {[string tolower [[$dpclass destructr] name]] == [string tolower $name]} { set proc [$dpclass destructr] } } } if {$proc == ""} { if {[$dpclass constructr] != ""} { if {[string tolower [[$dpclass constructr] name]] == [string tolower $name]} { set proc [$dpclass constructr] } } } if {$proc == ""} { # Obsolete code # m4_warning $W_OBSOLMETHOD $name set obsCode [TextSection new] $obsCode append "${line}\n" $obsCode appendSect $userTypes $obsCode append "begin\n" $obsCode appendSect $userCode $obsCode append "end;\n" if {[$dpclass obsoletecode] == ""} { $dpclass obsoletecode $obsCode } else { [$dpclass obsoletecode] appendSect $obsCode } return } # Dirty compare trick using target model! # set tempSection [TextSection new] $proc generateDefinition $tempSection $dpclass # Old code # if {[$tempSection contents] != $line} { set oldTypes [TextSection new] if {[$userTypes contents] != ""} { $oldTypes append "\{\$IFDEF OLDCODE\}\n" $oldTypes appendSect $userTypes $oldTypes append "\{\$ENDIF\}\n" } $proc usertypes $oldTypes set oldCode [TextSection new] if {[$userCode contents] != ""} { $oldCode append "\{\$IFDEF OLDCODE\}\n" $oldCode appendSect $userCode $oldCode append "\{\$ELSE\}\n" if {[$proc usercode] != ""} { $oldCode appendSect [$proc usercode] } else { $oldCode indent + $oldCode append "${DPCookie::implement0}\n" $oldCode indent - } $oldCode append "\{\$ENDIF\}\n" } $proc usercode $oldCode if {[$oldTypes contents] != "" || [$oldCode contents] != ""} { m4_warning $W_OLDCODEMETHOD $name } } else { $proc usercode $userCode $proc usertypes $userTypes } } method DPRegenerator::grabMethodBody {this fileDesc usercode usertypes} { # Note: This regenerator does not except multiple begin or ends on one line!!! # Get usertypes part # set done 0 set nestinglevel 0 set tempSection [TextSection new] while {![eof $fileDesc] && !$done} { set line [gets $fileDesc] if {[regexp ${DPCookie::endUserSection} $line] || [regexp {(([ ]+begin)|(^begin))(([ ]+)|([ ]*$))} $line]} { set done 1 if {[regexp {(([ ]+begin)|(^begin))(([ ]+)|([ ]*$))} $line]} { set nestinglevel 1 } } else { if {[regexp ${DPCookie::startUserSection} $line]} { set tempSection [TextSection new] } else { $tempSection append "$line\n" } } } # Only add section if not only white space if {[regexp {[^ ]*} $tempSection]} { $usertypes appendSect $tempSection } # Get usercode part # set done 0 set tempSection [TextSection new] while {![eof $fileDesc] && !$done} { set line [gets $fileDesc] if {[regexp {(([ ]+begin)|(^begin))(([ ]+)|([ ]*$))} $line total]} { incr nestinglevel } if {[regexp ${DPCookie::endUserSection} $line] || [regexp {(([ ]+end)|(^end));?(([ ]+)|([ ]*$))} $line total]} { if {[regexp {(([ ]+end)|(^end));?(([ ]+)|([ ]*$))} $line total]} { incr nestinglevel -1 if {$nestinglevel == 0} { set done 1 continue } } else { set done 1 continue } } else { if {[regexp ${DPCookie::startUserSection} $line]} { set tempSection [TextSection new] continue } } $tempSection append "$line\n" } # Only add section if not only white space if {[regexp {[^ ]*} [$tempSection contents]]} { $usercode appendSect $tempSection } return } method DPRegenerator::grabUserIncludes {this project class fileDesc} { set includes [TextSection new] set done 0 while {!$done} { if {[eof $fileDesc]} { m4_error $E_SYNTAX ${DPCookie::startUserInclude} "end of file" return } set line [gets $fileDesc] if {[regexp ${DPCookie::startUserInclude} $line]} { set done 1 } # If type declaration found, apparently no user includes exist if {[regexp "type" $line]} { return } } set done 0 while {!$done} { if {[eof $fileDesc]} { m4_error $E_SYNTAX ${DPCookie::endUserInclude} "end of file" return } set line [gets $fileDesc] if {[regexp ${DPCookie::endUserInclude} $line]} { set done 1 } else { $includes append "${line}\n" } } set dpclass [$project getUnit [$class getName]] if {$dpclass == "" || [$includes contents] == ""} { return } $dpclass userinclude $includes } method DPRegenerator::processCodeDef {this project class fileDesc} { set methodExpr {^[ ]*(class)?[ ]*(procedure|function|constructor|destructor)[ ]*([^.]*)\.([^(;:]*)(\(([^)]*)\))?[ ]*(:[ ]*([^ ]*))?;} set done 0 while {!$done} { if {[eof $fileDesc]} { m4_error $E_SYNTAX "implementation" "end of file" return } set line [gets $fileDesc] if {[regexp "implementation" $line]} { set done 1 } } set done 0 while {![eof $fileDesc] && !$done} { set line [gets $fileDesc] if {[regexp ${DPCookie::regenMarker} $line]} { set done 1 } else { if {[regexp $methodExpr $line total]} { set ucode [TextSection new] set utypes [TextSection new] $this grabMethodBody $fileDesc $ucode $utypes $this addUserCodeToMethod $project $class $total $utypes $ucode } } } if {![regexp ${DPCookie::regenMarker} $line]} { m4_error $E_SYNTAX ${DPCookie::regenMarker} "end of file" } } method DPRegenerator::grabComponentProperties {this fileDesc line form} { set objectExpr {^[ ]*(object)[ ]*([^:]*)([^$]*)} while {[regexp $objectExpr $line total dummy1 name type]} { if {[$form name] == $name} { set component $form } else { if {[[$form control] exists $name]} { set component [$form getControl $name] } else { m4_warning $W_OBSOLCOMPONENT $name # Skip (and remove) component while {![regexp {^[ ]*(end)[ ]*} $line]} { set line [gets $fileDesc] } continue } } set done 0 set tempSection [TextSection new] while {![eof $fileDesc] && !$done} { set line [gets $fileDesc] if {[regexp {^[ ]*(object)[ ]*} $line]} { set line [$this grabComponentProperties $fileDesc $line $form] } if {[regexp {^[ ]*(end)[ ]*} $line]} { set done 1 } else { # Do not add old event handlers # if {![regexp {[ ]+(on|before|after)[^ ]+} [string tolower $line]]} { regexp {[ ]*([^$]*)} $line total prop $tempSection append "${prop}\n" } } } # Add old properties # if {[regexp {[^ ]*} [$tempSection contents]]} { [$component properties] appendSect $tempSection } set line [gets $fileDesc] } return $line } # Generate all regeneration info from a form file. # # Note: All After/Before/On... properties are removed. # This is a trick to remove obsolete event handlers # without extensive checking. # method DPRegenerator::regenerateForm {this project class fileDesc} { set objectExpr {^[ ]*(object)[ ]*([^:]*)([^$]*)} # Search for form object set done 0 while {!$done} { if {[eof $fileDesc]} { m4_error $E_SYNTAX "end (of object)" "end of file" return } set line [gets $fileDesc] if {[regexp $objectExpr $line total dummy name type]} { set done 1 } } set form [$project getForm $name] $this grabComponentProperties $fileDesc $line $form } # Grab all regeneration info from an existing class file. # # Note: All TComponent classes are ignored. # method DPRegenerator::regenerate {this project class fileDesc} { # Process class file if {[$class baseType] != "TComponent"} { set sanity [$this sanityCheck $fileDesc] if {$sanity == 1} { m4_error $E_OBSOLETESECT [$class getName] return } else { if {$sanity == 2} { m4_error $E_OLDCODESECT [$class getName] return } } $this grabUserIncludes $project $class $fileDesc $this processCodeDef $project $class $fileDesc } } # Do not delete this line -- regeneration end marker