home *** CD-ROM | disk | FTP | other *** search
/ PC World 1998 October / PCWorld_1998-10_cd.bin / software / prehled / komix / DATA.Z / wrpex.tcl < prev    next >
Text File  |  1997-10-30  |  19KB  |  733 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            : @(#)wrpex.tcl    /main/titanic/7
  17. #       Original date   : Fri May  2 09:36:47 MET DST 1997
  18. #       Author          : heli
  19. #       Description     : Write Forte pex file from (selected) cex/hex files.
  20. #                         If '-hex-only' is specified, then only (selected)
  21. #                         hex files will be included. Else (selected) cex
  22. #                         files--plus needed hex files--will be included.
  23. #                         If no files of some type are are selected, then all
  24. #                         available files of that type will be used, if
  25. #                         needed.
  26. #
  27. #---------------------------------------------------------------------------
  28. # SccsId = @(#)wrpex.tcl    /main/titanic/7 30 Oct 1997 Copyright 1997 Cayenne Software Inc.
  29. #---------------------------------------------------------------------------
  30.  
  31. global SCCS_W;        set SCCS_W "
  32. @(#)wrpex.tcl    /main/titanic/7
  33. "
  34. global progName;    set progName "wrpex.tcl"
  35.  
  36. OTShRegister::objectCustomization
  37.  
  38. source [m4_path_name tcl cginit.tcl]
  39. require fstorage.tcl
  40. require caynutil.tcl
  41.  
  42. #------------------------------------------------------------------------------
  43.  
  44. Class SectionList : {GCObject} {
  45.     constructor
  46.     method destructor
  47.     method addSects
  48.     method getSection
  49.     method setSection
  50.     method removeSection
  51.     attribute section
  52. }
  53.  
  54. constructor SectionList {class this} {
  55.     set this [GCObject::constructor $class $this]
  56.     $this section [Dictionary new]
  57.     # Start constructor user section
  58.     # End constructor user section
  59.     return $this
  60. }
  61.  
  62. method SectionList::destructor {this} {
  63.     # Start destructor user section
  64.     # End destructor user section
  65. }
  66.  
  67. method SectionList::addSects {this nameList} {
  68.     foreach name $nameList {
  69.     if {[$this getSection $name] == ""} {
  70.         $this setSection $name [TextSection new]
  71.     }
  72.     }
  73. }
  74.  
  75. method SectionList::getSection {this name} {
  76.     return [[$this section] set $name]
  77. }
  78.  
  79. method SectionList::setSection {this name newSection} {
  80.     [$this section] set $name $newSection
  81. }
  82.  
  83. method SectionList::removeSection {this name} {
  84.     [$this section] unset $name
  85. }
  86.  
  87. #------------------------------------------------------------------------------
  88.  
  89. global guard
  90. set guard(includes)        "PROJECT INCLUDES"
  91. set guard(forward)        "FORWARD CLASS DECLARATIONS"
  92. set guard(forwardCursor)    "FORWARD CURSOR DECLARATIONS"
  93. set guard(constant)        "CONSTANT DEFINITIONS"
  94. set guard(C_datatype)        "C DATA TYPE DEFINITIONS"
  95. set guard(typedef)        "TYPEDEF DEFINITIONS"
  96. set guard(class)        "CLASS DEFINITIONS"
  97. set guard(service)        "SERVICE OBJECT DEFINITIONS"
  98. set guard(cursor)        "CURSOR DEFINITIONS"
  99. set guard(method)        "METHOD DEFINITIONS"
  100. set guard(eventHandler)        "EVENT HANDLER DEFINITIONS"
  101.  
  102. global handledFiles;        set handledFiles {}
  103.  
  104.  
  105. Class PEXwriter : GCObject {
  106.     attribute cc
  107.     attribute outList
  108.     attribute sectNameSet
  109.     attribute sections
  110.     attribute includesList
  111.     attribute forwardList
  112.     attribute forwardCursorList
  113.     attribute systemName
  114.     attribute hasErrors
  115.     constructor
  116.     method error
  117.     method warning
  118.     method message
  119.     method addOut
  120.     method addOutInclDeps
  121.     method addFile
  122.     method selectFiles
  123.     method doIncludes
  124.     method doForward
  125.     method doClass
  126.     method doInterface
  127.     method doCursor
  128.     method doService
  129.     method doConstant
  130.     method doTypedef
  131.     method doCdatatype
  132.     method parseFiles
  133.     method writeFiles
  134. }
  135.  
  136. constructor PEXwriter {class object} {
  137.     set this [GCObject::constructor $class $object]
  138.  
  139.     $this cc [ClientContext::global]
  140.     $this systemName [[[[$this cc] currentSystem] system] name]
  141.     $this outList [List new]
  142.     $this includesList [List new]
  143.     $this forwardList [List new]
  144.     $this forwardCursorList [List new]
  145.     $this hasErrors 0
  146.  
  147.     $this sectNameSet [List new]
  148.     [$this sectNameSet] contents {
  149.     header
  150.     includes
  151.     forward
  152.     forwardCursor
  153.     constant
  154.     C_datatype
  155.     typedef
  156.     class
  157.     service
  158.     cursor
  159.     method
  160.     eventHandler
  161.     trailer
  162.     }
  163.     $this sections [SectionList new]
  164.     [$this sections] addSects [[$this sectNameSet] contents]
  165.  
  166.     return $this
  167. }
  168.  
  169. method PEXwriter::error {this msg} {
  170.     puts stderr "ERROR \[$progName]: $msg."
  171.     $this hasErrors 1
  172. }
  173.  
  174. method PEXwriter::warning {this msg} {
  175.     puts stderr "WARNING \[$progName]: $msg."
  176. }
  177.  
  178. method PEXwriter::message {this msg} {
  179.     puts stderr "$msg."
  180. }
  181.  
  182. method PEXwriter::addOut {this file} {
  183.     if {[[$this outList] search $file] == -1} {
  184.     [$this outList] append $file
  185.     }
  186. }
  187.  
  188. method PEXwriter::addOutInclDeps {this file depTbl {_isRecCall 0}} {
  189.     global handledFiles
  190.     if {!$_isRecCall} {
  191.     set handledFiles {}
  192.     }
  193.     if {[$depTbl exists $file]} {
  194.     if {[lsearch -exact $handledFiles $file] != -1} {
  195.         # already handled
  196.         return
  197.     }
  198.     lappend handledFiles $file
  199.     [$depTbl set $file] foreach dep {
  200.         $this addOutInclDeps $dep $depTbl 1
  201.     }
  202.     }
  203.     $this addOut $file
  204. }
  205.  
  206. method PEXwriter::addFile {this fileList file} {
  207.     if {[$fileList search -exact $file] == -1} {
  208.     if {[fstorage::exists $file]} {
  209.         $fileList append $file
  210.     } else {
  211.         $this error "$file: no such file"
  212.     }
  213.     }
  214. }
  215.  
  216. method PEXwriter::selectFiles {this {argv {}}} {
  217.     # for an explanation, see `Description' at the top of this file
  218.     #
  219.     set hexOnly 0
  220.     set cfileList [List new]
  221.     set hfileList [List new]
  222.     while {![lempty $argv]} {
  223.     set arg [lvarpop argv]
  224.     switch -glob -- $arg {
  225.         -hex-only    {set hexOnly 1}
  226.         *.cex    {$this addFile $cfileList $arg}
  227.         *.hex    {$this addFile $hfileList $arg}
  228.         default    {$this warning "$arg: file of this type is ignored"}
  229.     }
  230.     }
  231.  
  232.     set doAllcex [$cfileList empty]
  233.     set doAllhex [$hfileList empty]
  234.     if {!$doAllcex && $hexOnly} {
  235.     $cfileList remove 0 end
  236.     }
  237.     if {!$doAllhex && !$hexOnly} {
  238.     $hfileList remove 0 end
  239.     }
  240.  
  241.     set cmsg ""
  242.     if {!$doAllcex} {
  243.     set cmsg " selected"
  244.     }
  245.     if {$hexOnly} {
  246.     set hmsg ""
  247.     if {!$doAllhex} {
  248.         set hmsg " from selected hex files"
  249.     }
  250.     $this message "Generating pex file$hmsg, while ignoring$cmsg cex files"
  251.     set doAllcex 0
  252.     } else {
  253.     $this message "Generating pex file from$cmsg cex files"
  254.     set doAllhex $doAllcex
  255.     }
  256.  
  257.     # get all hex files, and optionally all cex files
  258.     #
  259.     set allhfileList [List new]
  260.     foreach fileV [[[$this cc] currentSystem] localFileVersions] {
  261.     set type [[$fileV file] type]
  262.     if {$type == "hex"} {
  263.         $allhfileList append [[$fileV file] name].$type
  264.     } elseif {$doAllcex && $type == "cex"} {
  265.         $cfileList append [[$fileV file] name].$type
  266.     }
  267.     }
  268.     $allhfileList sort
  269.     $cfileList sort
  270.  
  271.     # get dependencies from hex files
  272.     #
  273.     set depTbl [Dictionary new]
  274.     $allhfileList foreach hfile {
  275.     if {[catch {set fd [fstorage::open $hfile r]} reason]} {
  276.         puts stderr $reason
  277.         return -1
  278.     }
  279.  
  280.     set readingDeps 0
  281.     set foundDep 0
  282.     while {![eof $fd]} {
  283.         set line [gets $fd]
  284.         if {[regexp "^-- dependency " $line]} {
  285.         set readingDeps 1
  286.         regexp {.*dependency ([^;]*);} $line dummy dependee
  287.         set dependee $dependee.hex
  288.         if {$dependee == $hfile} {
  289.             continue
  290.         }
  291.         set foundDep 1
  292.         if {![$depTbl exists $hfile]} {
  293.             # add slot for dependant in depTbl
  294.             $depTbl set $hfile [List new]
  295.         }
  296.         if {[[$depTbl set $hfile] search $dependee] == -1} {
  297.             # add dependee to dependant's list of dependees
  298.             [$depTbl set $hfile] append $dependee
  299.         }
  300.         } elseif {$readingDeps} {
  301.         break
  302.         }
  303.     }
  304.     if {!$foundDep && ($doAllhex || [$hfileList search $hfile] != -1)} {
  305.         $this addOut $hfile
  306.     }
  307.  
  308.     close $fd
  309.     }
  310.  
  311.     # add remaining hex files to outList, ordered properly
  312.     #
  313.     if {$doAllhex || $hexOnly} {
  314.     foreach hfile [$depTbl names] {
  315.         if {$doAllhex || [$hfileList search $hfile] != -1} {
  316.         $this addOutInclDeps $hfile $depTbl
  317.         }
  318.     }
  319.     } else {
  320.     $cfileList foreach cfile {
  321.         if {[regsub "\.cex$" $cfile ".hex" hfile]} {
  322.         $this addOutInclDeps $hfile $depTbl
  323.         }
  324.     }
  325.     }
  326.  
  327.     # finally if needed, add cex files to outList (in same order as hex files)
  328.     #
  329.     if {!$hexOnly} {
  330.     # we incrementally add to outList: not using List::foreach!!!
  331.     foreach hfile [[$this outList] contents] {
  332.         if {[regsub "\.hex$" $hfile ".cex" cfile]} {
  333.         if {[$cfileList search $cfile] != -1} {
  334.             $this addOut $cfile
  335.         }
  336.         }
  337.     }
  338.     }
  339.  
  340.     if {![[$this outList] empty]} {
  341.     $this message "Packing: [[$this outList] contents]"
  342.     }
  343.  
  344.     return 0
  345. }
  346.  
  347. method PEXwriter::doIncludes {this fd line} {
  348.     regexp {.*includes ([^;]*);} $line dummy include
  349.     if {[[$this includesList] search -exact $include] == -1 && $include != [$this systemName]} {
  350.     [$this includesList] append $include
  351.     }
  352.     return 0
  353. }
  354.  
  355. method PEXwriter::doForward {this fd line {takeLine 0}} {
  356.     # a forward may be a cursor forward
  357.     #
  358.     if {$takeLine} {
  359.     set theList forwardList
  360.     set forward $line
  361.     } elseif {[regexp {.*forward cursor .*} $line]} {
  362.     set theList forwardCursorList
  363.     regexp {.*forward cursor (.*);} $line dummy forward
  364.     } else {
  365.     set theList forwardList
  366.     regexp {.*forward (.*);} $line dummy forward
  367.     }
  368.     if {[[$this $theList] search -exact $forward] == -1} {
  369.     [$this $theList] append $forward
  370.     }
  371.     return 0
  372. }
  373.  
  374. method PEXwriter::doClass {this fd line type} {
  375.     # if 'hex' file then copy class declaration
  376.     #
  377.     if {$type == "hex"} {
  378.     set sect [[$this sections] getSection class]
  379.     $sect append "$line\n"
  380.  
  381.     regexp {class (.*) inherits} $line dummy forward
  382.     $this doForward $fd $forward 1
  383.  
  384.     while {![eof $fd]} {
  385.         set line [gets $fd]
  386.         if {[regexp "^end class;" $line]} {
  387.         $sect append "$line\n\n"
  388.         return 0
  389.         }
  390.         $sect append "$line\n"
  391.     }
  392.     $this warning "unexpected EOF; never did see 'end class;'"
  393.     return -1
  394.     }
  395.  
  396.     # this is a 'cex' file: skip class declaration
  397.     #
  398.     while {![eof $fd]} {
  399.     set line [gets $fd]
  400.     if {[regexp "^end class;" $line]} {
  401.         break
  402.     }
  403.     }
  404.     if {[eof $fd]} {
  405.     $this warning "unexpected EOF; never did see 'end class;'"
  406.     return -1
  407.     }
  408.  
  409.     # collect methods and event handlers
  410.     #
  411.     while {![eof $fd]} {
  412.     set line [gets $fd]
  413.     if {$line == "/* OBSOLETE_CODE *"} {
  414.         $this warning "file contains obsolete code section"
  415.         return -1
  416.     }
  417.     if {[regexp "^method " $line] || [regexp "^event handler " $line]} {
  418.         if {[regexp "^method " $line]} {
  419.         set sect [[$this sections] getSection method]
  420.         set kind method
  421.         } else {
  422.         set sect [[$this sections] getSection eventHandler]
  423.         set kind event
  424.         }
  425.         $sect append "------------------------------------------------------------\n$line\n"
  426.         while {![eof $fd]} {
  427.         set line [gets $fd]
  428.         if {[regexp "^end $kind;" $line]} {
  429.             $sect append "$line\n\n"
  430.             break
  431.         }
  432.         $sect append "$line\n"
  433.         }
  434.         if {[eof $fd]} {
  435.         $this warning "unexpected EOF; never did see 'end $kind;'"
  436.         return -1
  437.         }
  438.     }
  439.     }
  440.     return 0
  441. }
  442.  
  443. method PEXwriter::doInterface {this fd line type} {
  444.     # skip 'cex' file
  445.     #
  446.     if {$type == "cex"} {
  447.     return 0
  448.     }
  449.  
  450.     set sect [[$this sections] getSection class]
  451.     $sect append "$line\n"
  452.  
  453.     regexp {interface ([^ ]*)} $line dummy forward
  454.     $this doForward $fd "interface $forward" 1
  455.  
  456.     while {![eof $fd]} {
  457.     set line [gets $fd]
  458.     if {[regexp "^end interface;" $line]} {
  459.         $sect append "$line\n\n"
  460.         return 0
  461.     }
  462.     $sect append "$line\n"
  463.     }
  464.     $this warning "unexpected EOF; never did see 'end interface;'"
  465.     return -1
  466. }
  467.  
  468. method PEXwriter::doCursor {this fd line} {
  469.     # forward this cursor
  470.     #
  471.     regexp {^cursor ([^(]*)} $line dummy cursor
  472.     if {[[$this forwardCursorList] search -exact $cursor] == -1} {
  473.     [$this forwardCursorList] append $cursor
  474.     }
  475.  
  476.     # copy this cursor
  477.     #
  478.     set sect [[$this sections] getSection cursor]
  479.     $sect append "$line\n"
  480.     while {![eof $fd]} {
  481.     set line [gets $fd]
  482.     if {[regexp "^end;" $line]} {
  483.         $sect append "$line\n\n"
  484.         return 0
  485.     }
  486.     $sect append "$line\n"
  487.     }
  488.     $this warning "unexpected EOF; never did see 'end;'"
  489.     return -1
  490. }
  491.  
  492. method PEXwriter::doService {this fd line} {
  493.     set WS "\[ \t]*"
  494.     set sect [[$this sections] getSection service]
  495.     $sect append "$line\n"
  496.     while {![eof $fd]} {
  497.     set line [gets $fd]
  498.     if {[regexp "^${WS}$" $line]} {
  499.         continue
  500.     } elseif {[regexp "^${WS}--" $line]} {
  501.         continue
  502.     } else {
  503.         $sect append "$line\n"
  504.     }
  505.     }
  506.     return 0
  507. }
  508.  
  509. method PEXwriter::doConstant {this fd line} {
  510.     set sect [[$this sections] getSection constant]
  511.     $sect append "$line\n"
  512.     return 0
  513. }
  514.  
  515. method PEXwriter::doTypedef {this fd line type} {
  516.     if {$type == "hex"} {
  517.     set sect [[$this sections] getSection typedef]
  518.     $sect append "$line\n"
  519.     }
  520.     return 0
  521. }
  522.  
  523. method PEXwriter::doCdatatype {this fd line kind type} {
  524.     if {$type != "hex"} {
  525.     return 0
  526.     }
  527.     set sect [[$this sections] getSection C_datatype]
  528.     $sect append "$line\n"
  529.     while {![eof $fd]} {
  530.     set line [gets $fd]
  531.     if {[regexp "^end $kind;" $line]} {
  532.         $sect append "$line\n\n"
  533.         return 0
  534.     }
  535.     $sect append "$line\n"
  536.     }
  537.     $this warning "unexpected EOF; never did see 'end $kind;'"
  538.     return -1
  539. }
  540.  
  541. method PEXwriter::parseFiles {this} {
  542.     set WS "\[ \t]*"
  543.     [$this outList] foreach file {
  544.     switch -glob -- $file {
  545.         *.hex    {set type hex}
  546.         default    {set type cex}
  547.     }
  548.     if {[catch {set fd [fstorage::open $file r]} reason]} {
  549.         puts stderr $reason
  550.         $this warning "$file: file is skipped"
  551.         continue
  552.     }
  553.  
  554.     set status 0
  555.     while {![eof $fd]} {
  556.         set line [gets $fd]
  557.         if {[regexp "^${WS}$" $line]} {
  558.         continue
  559.         } elseif {[regexp "^-- includes " $line]} {
  560.         if {$type == "hex"} {
  561.             $this doIncludes $fd $line
  562.         }
  563.         } elseif {[regexp "^${WS}--" $line]} {
  564.         continue
  565.         } elseif {[string match forward* $line]} {
  566.         $this doForward $fd $line
  567.         } elseif {[string match class* $line]} {
  568.         set status [$this doClass $fd $line $type]
  569.         break
  570.         } elseif {[string match interface* $line]} {
  571.         set status [$this doInterface $fd $line $type]
  572.         break
  573.         } elseif {[string match cursor* $line]} {
  574.         set status [$this doCursor $fd $line]
  575.         break
  576.         } elseif {[string match service* $line]} {
  577.         $this doService $fd $line
  578.         break
  579.         } elseif {[string match constant* $line]} {
  580.         $this doConstant $fd $line
  581.         break
  582.         } elseif {[string match typedef* $line]} {
  583.         $this doTypedef $fd $line $type
  584.         break
  585.         } elseif {[string match enum* $line]} {
  586.         set status [$this doCdatatype $fd $line enum $type]
  587.         break
  588.         } elseif {[string match struct* $line]} {
  589.         set status [$this doCdatatype $fd $line struct $type]
  590.         break
  591.         } elseif {[string match union* $line]} {
  592.         set status [$this doCdatatype $fd $line union $type]
  593.         break
  594.         } else {
  595.         if {[info exists debug]} {$this warning "$file: unrecognized line is ignored: '$line'"}
  596.         }
  597.     }
  598.     if {$status} {
  599.         $this warning "$file: parse warning"
  600.     }
  601.  
  602.     fstorage::close $fd
  603.     }
  604. }
  605.  
  606. method PEXwriter::writeFiles {this {argv {}}} {
  607.     if {[$this selectFiles $argv] == -1} {
  608.     $this error "cannot generate pex file"
  609.     return -1
  610.     }
  611.  
  612.     $this parseFiles
  613.  
  614.     set fileName "[$this systemName].pex"
  615.  
  616.     # create header and trailer
  617.     #
  618.     set sect [[$this sections] getSection header]
  619.     $sect append "begin TOOL [$this systemName];\n"
  620.     $sect append "\n"
  621.     expandHeaderIntoSection $fileName forte $sect
  622.     set sect [[$this sections] getSection trailer]
  623.     $sect append "\nend [$this systemName];\n"
  624.  
  625.     # process includes
  626.     #
  627.     set sect [[$this sections] getSection includes]
  628.     [$this includesList] foreach include {
  629.     if {$include != ""} {
  630.         $sect append "includes $include;\n"
  631.     }
  632.     }
  633.  
  634.     # process forwards
  635.     #
  636.     set sect [[$this sections] getSection forward]
  637.     [$this forwardList] foreach forward {
  638.     if {$forward != ""} {
  639.         $sect append "forward $forward;\n"
  640.     }
  641.     }
  642.  
  643.     # process cursor forwards
  644.     #
  645.     set sect [[$this sections] getSection forwardCursor]
  646.     [$this forwardCursorList] foreach forward {
  647.     if {$forward != ""} {
  648.         $sect append "forward cursor $forward;\n"
  649.     }
  650.     }
  651.  
  652.     # write all to one section
  653.     #
  654.     set sect [TextSection new]
  655.     [$this sectNameSet] foreach sectName {
  656.     set genSect [[$this sections] getSection $sectName]
  657.     set guardStr ""
  658.     if {[info exists guard($sectName)]} {
  659.         set guardStr $guard($sectName)
  660.         $sect append "\n-- START $guardStr\n"
  661.     }
  662.     if {[$genSect contents] != ""} {
  663.         $sect appendSect $genSect
  664.         #$sect append "\n"
  665.     }
  666.     if {$guardStr != ""} {
  667.         $sect append "-- END $guardStr\n"
  668.     }
  669.     }
  670.  
  671.     if {[info exists debug]} {puts -nonewline stderr [$sect contents]}
  672.  
  673.     if {[catch {set fd [fstorage::open $fileName w]} reason]} {
  674.     puts stderr $reason
  675.     $this error "cannot continue generating pex file"
  676.     return -1
  677.     }
  678.     $sect write $fd
  679.     fstorage::close $fd
  680.     $this message "Wrote pex file '$fileName'"
  681.     return 0
  682. }
  683.  
  684. #------------------------------------------------------------------------------
  685.  
  686. proc setProg {} {
  687.     set name [string trim $SCCS_W "\n%"]
  688.     if {$name != "W"} {
  689.     regexp "@.#.(.*)\t" $name dummy name
  690.     global progName
  691.     set progName $name
  692.     }
  693. }
  694.  
  695. proc main {{argv {}}} {
  696.     # usage: main {file1 file2 ...} , where list of files is optional
  697.     #
  698.     set cc [ClientContext::global]
  699.     set phaseV [$cc currentPhase]
  700.     if {[$phaseV isNil] || [[$phaseV phase] type] != "Implementation"} {
  701.     puts stderr "ERROR\[$progName]: phase type must be 'Implementation'."
  702.     return -1
  703.     }
  704.     if {[[$cc currentSystem] isNil]} {
  705.     puts stderr "ERROR\[$progName]: client context must be at system level."
  706.     return -1
  707.     }
  708.  
  709.     set pexWriter [PEXwriter new]
  710.     $pexWriter writeFiles $argv
  711.     return [$pexWriter hasErrors]
  712. }
  713.  
  714. #------------------------------------------------------------------------------
  715.  
  716.  
  717.  
  718. setProg
  719.  
  720. puts stderr "Generate pex File"
  721. puts stderr "=================\n"
  722.  
  723. if {[catch {set status [main $argv]} reason]} {
  724.     puts stderr $reason
  725.     puts stderr "Failed to write pex file."
  726. } else {
  727.     if {$status} {
  728.     puts stderr "Failed to write pex file."
  729.     }
  730. }
  731.  
  732. puts stderr "\n`Generate pex File' finished"
  733.