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 >
Text File  |  1997-12-01  |  14KB  |  549 lines

  1. #---------------------------------------------------------------------------
  2. #
  3. # Copyright (c) 1997 by Cayenne Software, Inc.
  4. #
  5. # This software is furnished under a license and may be used only in
  6. # accordance with the terms of such license and with the inclusion of
  7. # the above copyright notice. This software or any other copies thereof
  8. # may not be provided or otherwise made available to any other person.
  9. # No title to and ownership of the software is hereby transferred.
  10. #
  11. # The information in this software is subject to change without notice
  12. # and should not be construed as a commitment by Cayenne Software, Inc.
  13. #
  14. #---------------------------------------------------------------------------
  15. #
  16. #       File            : cppgentor.tcl
  17. #       Author          : 
  18. #       Original date   : November 1997
  19. #       Description     : Classes for code generation
  20. #
  21. #---------------------------------------------------------------------------
  22.  
  23. #---------------------------------------------------------------------------
  24. #      File:           @(#)cppfilehan.tcl    /main/titanic/2
  25. #---------------------------------------------------------------------------
  26.  
  27. # Start user added include file section
  28. # End user added include file section
  29.  
  30. require "filehandle.tcl"
  31.  
  32. Class CppFileHandler : {FileHandler} {
  33.     constructor
  34.     method destructor
  35.     method promotor
  36.     method getSpecialFiles
  37.     method getFileTypes
  38.     method getMakefileName
  39.     attribute hdrType
  40.     attribute cppType
  41. }
  42.  
  43. constructor CppFileHandler {class this} {
  44.     set this [FileHandler::constructor $class $this]
  45.     # Start constructor user section
  46.     $this promotor
  47.     # End constructor user section
  48.     return $this
  49. }
  50.  
  51. method CppFileHandler::destructor {this} {
  52.     # Start destructor user section
  53.     # End destructor user section
  54.     $this FileHandler::destructor
  55. }
  56.  
  57. method CppFileHandler::promotor {this} {
  58.     # Should get this information from the repository
  59.     $this hdrType "h++"
  60.     $this cppType "c++"
  61. }
  62.  
  63. method CppFileHandler::getSpecialFiles {this} {
  64.     set list [List new]
  65.     $list append [$this getMakefileName]
  66.     return $list
  67. }
  68.  
  69. method CppFileHandler::getFileTypes {this} {
  70.     set list [List new]
  71.     $list append [$this hdrType]
  72.     $list append [$this cppType]
  73.     return $list
  74. }
  75.  
  76. method CppFileHandler::getMakefileName {this} {
  77.     return "makefile"
  78. }
  79.  
  80. # Do not delete this line -- regeneration end marker
  81.  
  82. #---------------------------------------------------------------------------
  83. #      File:           @(#)cppconstan.tcl    /main/titanic/2
  84. #---------------------------------------------------------------------------
  85.  
  86. # Start user added include file section
  87. # End user added include file section
  88.  
  89.  
  90. Class CppConstants : {Object} {
  91.     constructor
  92.     method destructor
  93. }
  94.  
  95. global CppConstants::startInclude
  96. set CppConstants::startInclude "Start user added include file section"
  97.  
  98. global CppConstants::endInclude
  99. set CppConstants::endInclude "End user added include file section"
  100.  
  101. global CppConstants::startDtor
  102. set CppConstants::startDtor "Start destructor user section"
  103.  
  104. global CppConstants::endDtor
  105. set CppConstants::endDtor "End destructor user section"
  106.  
  107. global CppConstants::startCtor
  108. set CppConstants::startCtor "Start constructor user section"
  109.  
  110. global CppConstants::endCtor
  111. set CppConstants::endCtor "End constructor user section"
  112.  
  113. global CppConstants::regenEnd
  114. set CppConstants::regenEnd "Do not delete this line -- regeneration end marker"
  115.  
  116. global CppConstants::obsoleteCode
  117. set CppConstants::obsoleteCode "OBSOLETE_CODE"
  118.  
  119. global CppConstants::oldCode
  120. set CppConstants::oldCode "OLDCODE"
  121.  
  122.  
  123. constructor CppConstants {class this name} {
  124.     set this [Object::constructor $class $this $name]
  125.     # Start constructor user section
  126.     # End constructor user section
  127.     return $this
  128. }
  129.  
  130. method CppConstants::destructor {this} {
  131.     # Start destructor user section
  132.     # End destructor user section
  133. }
  134.  
  135. # Do not delete this line -- regeneration end marker
  136.  
  137. #---------------------------------------------------------------------------
  138. #      File:           @(#)cppregener.tcl    /main/titanic/9
  139. #---------------------------------------------------------------------------
  140.  
  141. # Start user added include file section
  142. # End user added include file section
  143.  
  144. require "regenerato.tcl"
  145.  
  146. Class CppRegenerator : {Regenerator} {
  147.     constructor
  148.     method destructor
  149.     method checkFile
  150.     method processUserIncs
  151.     method processCtorDtor
  152.     method processUserDefMeth
  153.     method regenerate
  154. }
  155.  
  156. constructor CppRegenerator {class this} {
  157.     set this [Regenerator::constructor $class $this]
  158.     # Start constructor user section
  159.     # End constructor user section
  160.     return $this
  161. }
  162.  
  163. method CppRegenerator::destructor {this} {
  164.     # Start destructor user section
  165.     # End destructor user section
  166.     $this Regenerator::destructor
  167. }
  168.  
  169. method CppRegenerator::checkFile {this fileName fileDesc fileType} {
  170.     set brace 0
  171.     seek $fileDesc 0
  172.     set line [gets $fileDesc]
  173.     set obsoleteTxt "#ifdef ${CppConstants::obsoleteCode}"
  174.     set oldTxt "#ifdef ${CppConstants::oldCode}"
  175.  
  176.     while {![eof $fileDesc]} { 
  177.         if {[regexp "^$oldTxt" $line] || [regexp "^$obsoleteTxt" $line] } {
  178.             m4_error $E_CONTAINSOLD $fileName ${CppConstants::obsoleteCode} ${CppConstants::oldCode}
  179.             return 0
  180.         }
  181.  
  182.         if {(![regexp {^\};$} $line]) || ($fileType != "hdr") } {
  183.             if {[regexp {^\}.+} $line] || [regexp {^\{.+} $line]} {
  184.                 m4_error $E_UNMATCHBRACES $fileName
  185.                 return 0
  186.             }
  187.         }
  188.         if {[regexp {^\{$} $line] } {
  189.             incr brace
  190.         }
  191.         if {[regexp {^\}$} $line] } {
  192.             if {$brace >= 1} {
  193.                 incr brace -1
  194.             } else {
  195.                 m4_error $E_UNMATCHBRACES $fileName
  196.                 return 0
  197.             }
  198.         }
  199.         set line [gets $fileDesc]
  200.     }
  201.  
  202.     if {$brace != 0} {
  203.         m4_error $E_UNMATCHBRACES $fileName
  204.         return 0
  205.     }
  206.     return 1
  207. }
  208.  
  209. method CppRegenerator::processUserIncs {this class fileDesc fileType} {
  210.     set sect [$class getIncludeSect $fileType]
  211.     set includeLine 0
  212.     seek $fileDesc 0
  213.     set line [gets $fileDesc]
  214.     while {![eof $fileDesc]} {
  215.         
  216.         if [regexp "^// ${CppConstants::endInclude}\$" $line] {
  217.             break
  218.         }
  219.         if {$includeLine} {
  220.             $sect append $line
  221.             $sect append "\n"
  222.         }
  223.         if [regexp "^// ${CppConstants::startInclude}\$" $line] {
  224.             set includeLine 1
  225.         }
  226.  
  227.         set line [gets $fileDesc]
  228.     }
  229.  
  230.     if [eof $fileDesc] {
  231.         seek $fileDesc 0
  232.         return 0
  233.     }
  234.     return 1
  235. }
  236.  
  237. method CppRegenerator::processCtorDtor {this class fileDesc fileType} {
  238.     if { $fileType == "hdr" } {
  239.         return 
  240.     }
  241.     if {![$class isA CppClass]} {
  242.         return
  243.     }
  244.  
  245.     set line [gets $fileDesc]
  246.  
  247.     set stage 0
  248.  
  249.     set ctorSect ""
  250.     set dtorSect ""
  251.  
  252.     # Find constructor and destructor (if there are any).
  253.     [$class featureSet] foreach feature {
  254.         if [$feature isA CppConstructor] {
  255.             set ctorSect [CppRegen new $feature]
  256.         }
  257.         if [$feature isA CppDestructor] {
  258.             set dtorSect [CppRegen new $feature]
  259.         }
  260.     }
  261.  
  262.     set obsolete 0
  263.     if {$ctorSect == ""} {
  264.         set obsolete 1
  265.         set ctorSect [$class getObsoleteCode $fileType]
  266.     }
  267.  
  268.     while {![eof $fileDesc]} {
  269.         
  270.         if {[regexp "// ${CppConstants::endDtor}\$" $line] &&
  271.             ($stage == 3)} {
  272.            break
  273.         }
  274.         if {$stage == 3} {
  275.             if {$dtorSect != ""} {
  276.                 $dtorSect append $line
  277.                 $dtorSect append "\n"
  278.             }
  279.         }
  280.         if {[regexp "// ${CppConstants::startDtor}\$" $line]} {
  281.             set stage 3
  282.         }
  283.  
  284.         if {[regexp "// ${CppConstants::endCtor}\$" $line] &&
  285.             ($stage == 1)} {
  286.             if {$obsolete} {
  287.                 $ctorSect append "\}\n"
  288.             }
  289.             set stage 2
  290.         }
  291.         if {$stage == 1} {
  292.             if {$ctorSect != ""} {
  293.                 $ctorSect append $line
  294.                 $ctorSect append "\n"
  295.             }
  296.         }
  297.         if {[regexp "// ${CppConstants::startCtor}\$" $line] &&
  298.             ($stage == 0)} {
  299.             if {$obsolete} {
  300.                 $ctorSect append "void obsoleteUserSectOfCtor()\n"
  301.                 $ctorSect append "\{\n"
  302.             }
  303.             set stage 1
  304.         }
  305.  
  306.         set line [gets $fileDesc]
  307.     }
  308.  
  309.     if [eof $fileDesc] {
  310.         lseek $fileDesc 0 start
  311.     }
  312. }
  313.  
  314. method CppRegenerator::processUserDefMeth {this class fileDesc fileType} {
  315.     set exp_method {^(.+ )?([&*]*)[^: ]+::([^\(]+)\(([^\)]*)\).*$}
  316.  
  317.     set line [gets $fileDesc]
  318.  
  319.     set sect ""
  320.  
  321.     while {(![eof $fileDesc]) &&
  322.            (![regexp "^// ${CppConstants::regenEnd}" $line])} {
  323.  
  324.         if [regexp $exp_method $line dummy type modifiers methodName params] {
  325.             set signatureLine $line
  326.             set signature ""
  327.  
  328.             foreach param [split $params ","] {
  329.                 if [regexp {^(const )?([^*&]+)(&)?(\*)?( [^ ]+)$} \
  330.                         [string trim $param] dummy constDef planeType ref ptr name] {
  331.                     set signature "${signature}${planeType}${ptr}|"
  332.                 } else {
  333.                     set signature "${signature}|"
  334.                 }
  335.             }
  336.  
  337.             set foundFeature ""
  338.             if [$class isA CppClass] {
  339.                 [$class featureSet] foreach feature {
  340.                     if {($methodName == [$feature getName]) &&
  341.                         [$feature isA CppUserMethod] &&
  342.                         [[$feature regenSet] empty]} {
  343.  
  344.                         set featureSig ""
  345.                         [$feature paramSet] foreach param {
  346.                             set ptype [[$param type] getTypeName "" $class]
  347.                             if [regexp {^(const )?([^*&]+)(&)?(\*)?$} $ptype dummy constDef planeType ref ptr] {
  348.                                 if [[$param type] isArray] {
  349.                                     set constDef "const "
  350.                                     set ptr "*"
  351.                                 }
  352.                                 if [[$param type] isPointer] {
  353.                                     set ptr "*"
  354.                                 }
  355.     
  356.                                 set featureSig "${featureSig}${planeType}${ptr}|"
  357.                             } else {
  358.                                 set featureSig "${featureSig}|"
  359.                             }
  360.                         }
  361.     
  362.                         if {$featureSig == $signature} {
  363.                             set foundFeature $feature
  364.                             break
  365.                         }
  366.                     }
  367.                 }
  368.             }
  369.  
  370.             set userBody [TextSection new]
  371.             set line [gets $fileDesc]
  372.             if {![regexp "^\{" $line]} {
  373.                 m4_error $E_SYNTAX "Unexpected '$line'"
  374.             }
  375.  
  376.             set line [gets $fileDesc]
  377.             while {(![eof $fileDesc]) && (![regexp "^\}" $line])} {
  378.                 $userBody append "$line\n"
  379.                 set line [gets $fileDesc]
  380.             }
  381.  
  382.             if {$foundFeature == ""} {
  383.                 set obsoleteName($signature) $methodName
  384.                 set obsoleteCode($signature) $userBody
  385.                 set obsoleteLine($signature) $signatureLine
  386.             } else {
  387.                 set mUserBody [CppRegen new $foundFeature]
  388.                 $mUserBody appendSect $userBody
  389.             }
  390.         }
  391.         set line [gets $fileDesc]
  392.     }
  393.  
  394.     if [array exists obsoleteName] {
  395.         foreach signature [array names obsoleteName] {
  396.             [$class featureSet] foreach feature {
  397.                 if {[$feature getName] == $obsoleteName($signature) &&
  398.                     [[$feature regenSet] empty]} {
  399.                     if {$fileType == "hdr"} {
  400.                         m4_warning $W_GENOCODE ${CppConstants::oldCode} [$class hdrFileName]
  401.                     } else {
  402.                         m4_warning $W_GENOCODE ${CppConstants::oldCode} [$class cppFileName]
  403.                     }
  404.                     set mUserBody [CppRegen new $feature]
  405.                     $mUserBody append "#ifdef ${CppConstants::oldCode}\n"
  406.                     $mUserBody appendSect $obsoleteCode($signature)
  407.                     $mUserBody append "#else // ${CppConstants::oldCode}\n"
  408.                     $mUserBody indent +
  409.                     $mUserBody append "// insert new implementation here\n"
  410.                     $mUserBody indent -
  411.                     $mUserBody append "#endif // ${CppConstants::oldCode}\n"
  412.                     unset obsoleteName($signature)
  413.                     unset obsoleteCode($signature)
  414.                     unset obsoleteLine($signature)
  415.                     break
  416.                 }
  417.             }
  418.         }
  419.     }
  420.  
  421.     if [array exists obsoleteName] {
  422.         foreach signature [array names obsoleteName] {
  423.             set sect [$class getObsoleteCode $fileType]
  424.             $sect append $obsoleteLine($signature)
  425.             $sect append "\n\{\n"
  426.             $sect appendSect $obsoleteCode($signature)
  427.             $sect append "\}\n\n"
  428.         }
  429.     }
  430. }
  431.  
  432. method CppRegenerator::regenerate {this class fileDesc fileType} {
  433.     if {$fileType == "hdr"} {
  434.         set fileName [$class hdrFileName]
  435.     } else {
  436.         set fileName [$class cppFileName]
  437.     }
  438.     if [$this checkFile $fileName $fileDesc $fileType] {
  439.         set hasUserIncs [$this processUserIncs $class $fileDesc $fileType]
  440.         if {(!$hasUserIncs) && $fileType == "hdr"} {
  441.             # In header files generated by pre-7.1.1 there can't be user-defined
  442.             # methods in the header file
  443.             m4_warning $W_UPGRADE [$class name]
  444.         } else {
  445.             $this processCtorDtor $class $fileDesc $fileType
  446.             $this processUserDefMeth $class $fileDesc $fileType
  447.         }
  448.         return 1
  449.     }
  450.     return 0
  451. }
  452.  
  453. # Do not delete this line -- regeneration end marker
  454.  
  455. #---------------------------------------------------------------------------
  456. #      File:           @(#)cppgenerat.tcl    /main/titanic/7
  457. #---------------------------------------------------------------------------
  458.  
  459. # Start user added include file section
  460. global dontCallMakeMake
  461. set dontCallMakeMake 1
  462. require makemake.tcl
  463. # End user added include file section
  464.  
  465. require "generator.tcl"
  466.  
  467. Class CppGenerator : {Generator} {
  468.     constructor
  469.     method destructor
  470.     method promotor
  471.     method generate
  472.     method check
  473.     method generateSpecialFiles
  474.     attribute fileHandler
  475. }
  476.  
  477. constructor CppGenerator {class this} {
  478.     set this [Generator::constructor $class $this]
  479.     # Start constructor user section
  480.     $this promotor
  481.     # End constructor user section
  482.     return $this
  483. }
  484.  
  485. method CppGenerator::destructor {this} {
  486.     # Start destructor user section
  487.     # End destructor user section
  488.     $this Generator::destructor
  489. }
  490.  
  491. method CppGenerator::promotor {this} {
  492.     $this fileHandler [CppFileHandler new]
  493. }
  494.  
  495. method CppGenerator::generate {this classList} {
  496.     set ok 1
  497.     set typeToClassDict [Dictionary new]
  498.     set tgtModel [CppModel new]
  499.     set regen [CppRegenerator new]
  500.     set ooplToTarget [Dictionary new]
  501.     puts "Generating target language model..."
  502.     $classList foreach cl {
  503.         set tclass [$cl generate $tgtModel]
  504.         $ooplToTarget set $cl $tclass
  505.     }
  506.     $tgtModel setFileNameParams [$this fileHandler]
  507.     puts "(Re)generating source files..."
  508.     $classList foreach cl {
  509.         set tclass [$ooplToTarget set $cl]
  510.         set fileDesc [[$this fileHandler] \
  511.             openFile $cl [[$this fileHandler] hdrType]]
  512.         if {$fileDesc != ""} {
  513.             if {![$regen regenerate $tclass $fileDesc "hdr"]} {
  514.                 set ok 0
  515.             }
  516.             [$this fileHandler] closeFile $fileDesc
  517.         }
  518.         set fileDesc [[$this fileHandler] \
  519.             openFile $cl [[$this fileHandler] cppType]]
  520.         if {$fileDesc != ""} {
  521.             if {![$regen regenerate $tclass $fileDesc "cpp"]} {
  522.                 set ok 0
  523.             }
  524.             [$this fileHandler] closeFile $fileDesc
  525.         }
  526.     }
  527.     if {$ok} {
  528.         $tgtModel generate $typeToClassDict
  529.     }
  530.     return $typeToClassDict
  531. }
  532.  
  533. method CppGenerator::check {this classList} {
  534.     $classList foreach class {
  535.         $class check
  536.     }
  537. }
  538.  
  539. method CppGenerator::generateSpecialFiles {this fileList} {
  540.     foreach file $fileList {
  541.         if { $file == "makefile" } {
  542.             makemake
  543.         }
  544.     }
  545. }
  546.  
  547. # Do not delete this line -- regeneration end marker
  548.  
  549.