Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:21

0001 #!/bin/sh
0002 # The next line restarts using tclsh \
0003 exec tclsh "$0" ${1+"$@"}
0004 
0005 #
0006 # This script ports the "geners" generic binary I/O
0007 # package to CMSSW. The porting consists in
0008 #
0009 # 1. Changing various "#include" CPP definitions so that
0010 #    they pick up the files from the corresponding CMSSW
0011 #    location.
0012 #
0013 # 2. Changing all exceptions so that they inherit from
0014 #    cms::Exception instead of std::exception.
0015 #
0016 # 3. Replacing LOKI_STATIC_CHECK statements by static_assert.
0017 #
0018 # You only need to modify the three main variables defined below,
0019 # the rest will be done by the script.
0020 #
0021 # After porting, check the contents of "IOException.hh" file.
0022 # The current procedure simply hardwires certain line numbers
0023 # to replace in that file, and might fail in the future in case
0024 # file contents are changed.
0025 #
0026 set inputdir "/afs/cern.ch/user/i/igv/local/src/geners-1.3.0/geners"
0027 set dest_package "Alignment/Geners"
0028 set packagedir "/afs/cern.ch/user/i/igv/CMSSW_7_1_0_pre4/src/Alignment/Geners"
0029 
0030 # Create the map for changing include statements
0031 set includemap [list "\#include \"geners/static_check.h\"" {}]
0032 lappend includemap LOKI_STATIC_CHECK static_assert
0033 lappend includemap "\#include \"geners/" "\#include \"$dest_package/interface/"
0034 
0035 # Take care of exceptions so that they comply with CMSSW guidelines
0036 lappend includemap std::length_error gs::IOLengthError
0037 lappend includemap std::out_of_range gs::IOOutOfRange
0038 lappend includemap std::invalid_argument gs::IOInvalidArgument
0039 lappend includemap "\#include <stdexcept>" "\#include \"$dest_package/interface/IOException.hh\""
0040 
0041 proc file_contents {filename} {
0042     set chan [open $filename "r"]
0043     set contents [read $chan [file size $filename]]
0044     close $chan
0045     set contents
0046 }
0047 
0048 proc filemap {infile outfile map} {
0049     set in_data [file_contents $infile]
0050     set chan [open $outfile "w"]
0051     puts -nonewline $chan [string map $map $in_data]
0052     close $chan
0053 }
0054 
0055 # Procedures for reinserting .icc files
0056 proc is_icc_line {line} {
0057     set trline [string trim $line]
0058     if {[string first "\#include" $trline] != 0} {
0059         return 0
0060     }
0061     if {[string compare [string range $trline end-4 end] ".icc\""]} {
0062         return 0
0063     }
0064     return 1
0065 }
0066 
0067 proc icc_contents {icc_line icc_dir} {
0068     set trline [string trim $icc_line]
0069     set fname [string trim [lindex [split $trline /] end] "\""]
0070     file_contents [file join $icc_dir $fname]
0071 }
0072 
0073 proc insert_icc {infile outfile icc_dir} {
0074     set output [list]
0075     foreach line [split [file_contents $infile] "\n"] {
0076         if {[is_icc_line $line]} {
0077             lappend output [icc_contents $line $icc_dir]
0078         } else {
0079             lappend output $line
0080         }
0081     }
0082     set chan [open $outfile "w"]
0083     puts $chan [join $output "\n"]
0084     close $chan
0085 }
0086 
0087 # Other useful procedures
0088 proc replace_lines {infile outfile from to replacement} {
0089     set output [list]
0090     set linenum 1
0091     foreach line [split [file_contents $infile] "\n"] {
0092         set skip 0
0093         set replace 0
0094         if {$linenum >= $from && $linenum <= $to} {
0095             set skip 1
0096         }
0097         if {$skip} {
0098             if {$linenum == $to} {
0099                 set replace 1
0100             }
0101         }
0102         if {$replace} {
0103             lappend output $replacement
0104         }
0105         if {!$skip} {
0106             lappend output $line
0107         }
0108         incr linenum
0109     }
0110     set chan [open $outfile "w"]
0111     puts $chan [join $output "\n"]
0112     close $chan
0113 }
0114 
0115 proc tempfile {dir} {
0116     set chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
0117     set nrand_chars 10
0118     set maxtries 10
0119     set access [list RDWR CREAT EXCL TRUNC]
0120     set permission 0600
0121     set channel ""
0122     set checked_dir_writable 0
0123     set mypid [pid]
0124     for {set i 0} {$i < $maxtries} {incr i} {
0125         set newname ""
0126         for {set j 0} {$j < $nrand_chars} {incr j} {
0127             append newname [string index $chars \
0128                     [expr ([clock clicks] ^ $mypid) % 62]]
0129         }
0130         set newname [file join $dir $newname]
0131         if {[file exists $newname]} {
0132             after 1
0133         } else {
0134             if {[catch {open $newname $access $permission} channel]} {
0135                 if {!$checked_dir_writable} {
0136                     set dirname [file dirname $newname]
0137                     if {![file writable $dirname]} {
0138                         error "Directory $dirname is not writable"
0139                     }
0140                     set checked_dir_writable 1
0141                 }
0142             } else {
0143                 # Success
0144                 close $channel
0145                 return $newname
0146             }
0147         }
0148     }
0149     if {[string compare $channel ""]} {
0150         error "Failed to open a temporary file: $channel"
0151     } else {
0152         error "Failed to find an unused temporary file name"
0153     }
0154 }
0155 
0156 proc process_static_assert {lines} {
0157     set code [join $lines "\n"]
0158     set comma [string first "," $code]
0159     set end [string first ")" $code $comma]
0160     set statement [string range $code [expr {$comma+1}] [expr {$end-1}]]
0161     set newstatement [string map {_ { }} [string trim $statement]]
0162     set newtext "[string range $code 0 $comma] \"$newstatement\");"
0163 }
0164 
0165 proc fix_static_assert {infile outfile} {
0166     set in_assert 0
0167     set output [list]
0168     set assert_lines [list]
0169     foreach line [split [file_contents $infile] "\n"] {
0170         if {!$in_assert} {
0171             if {[string first "static_assert" $line] >= 0} {
0172                 set in_assert 1
0173             }
0174         }
0175         if {$in_assert} {
0176             lappend assert_lines $line
0177             if {[string first ";" $line] >= 0} {
0178                 lappend output [process_static_assert $assert_lines]
0179                 set assert_lines [list]
0180                 set in_assert 0
0181             }        
0182         } else {
0183             lappend output $line
0184         }
0185     }
0186     set chan [open $outfile "w"]
0187     puts -nonewline $chan [join $output "\n"]
0188     close $chan
0189 }
0190 
0191 # Now, do the replacements
0192 foreach hh [glob "$inputdir/*.hh"] {
0193     set tempfile [tempfile /tmp]
0194     set outfile [file join "$packagedir/interface" [file tail $hh]]
0195     insert_icc $hh $tempfile $inputdir
0196     filemap $tempfile $outfile $includemap
0197     file delete $tempfile
0198     fix_static_assert $outfile $outfile
0199 }
0200 
0201 foreach cc [glob "$inputdir/*.cc"] {
0202     set outfile [file join "$packagedir/src" [file tail $cc]]
0203     filemap $cc $outfile $includemap
0204 }
0205 
0206 # Update the IOException.hh file
0207 set update {
0208 #include "FWCore/Utilities/interface/Exception.h"
0209 
0210 namespace gs {
0211     /** Base class for the exceptions specific to the Geners I/O library */
0212     struct IOException : public cms::Exception
0213     {
0214         inline IOException() : cms::Exception("gs::IOException") {}
0215 
0216         inline explicit IOException(const std::string& description)
0217             : cms::Exception(description) {}
0218 
0219         inline explicit IOException(const char* description)
0220             : cms::Exception(description) {}
0221 
0222         virtual ~IOException() throw() {}
0223     };
0224 
0225     struct IOLengthError : public IOException
0226     {
0227         inline IOLengthError() : IOException("gs::IOLengthError") {}
0228 
0229         inline explicit IOLengthError(const std::string& description)
0230             : IOException(description) {}
0231 
0232         virtual ~IOLengthError() throw() {}
0233     };
0234 
0235     struct IOOutOfRange : public IOException
0236     {
0237         inline IOOutOfRange() : IOException("gs::IOOutOfRange") {}
0238 
0239         inline explicit IOOutOfRange(const std::string& description)
0240             : IOException(description) {}
0241 
0242         virtual ~IOOutOfRange() throw() {}
0243     };
0244 
0245     struct IOInvalidArgument : public IOException
0246     {
0247         inline IOInvalidArgument() : IOException("gs::IOInvalidArgument") {}
0248 
0249         inline explicit IOInvalidArgument(const std::string& description)
0250             : IOException(description) {}
0251 
0252         virtual ~IOInvalidArgument() throw() {}
0253     };
0254 
0255     /* Automatic replacement end} */
0256 }
0257 
0258 set infile "$inputdir/IOException.hh"
0259 set outfile "$packagedir/interface/IOException.hh"
0260 replace_lines $infile $outfile 5 24 $update
0261 
0262 # Port the C++11 configuration part
0263 file copy -force "$packagedir/interface/CPP11_config_enable.hh" "$packagedir/interface/CPP11_config.hh"
0264 file delete "$packagedir/interface/CPP11_config_disable.hh" "$packagedir/interface/CPP11_config_enable.hh"
0265 
0266 # Fix the programs from the "tools" section of geners
0267 foreach hh [glob "$inputdir/../tools/*.hh"] {
0268     set outfile [file join "$packagedir/test" [file tail $hh]]
0269     filemap $hh $outfile $includemap
0270 }
0271 
0272 foreach cc [glob "$inputdir/../tools/*.cc"] {
0273     set outfile [file join "$packagedir/test" [file tail $cc]]
0274     filemap $cc $outfile $includemap
0275 }