1 #!/usr/bin/perl -w 2 3 # Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # 1. Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # 2. Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 # its contributors may be used to endorse or promote products derived 16 # from this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 # Used for splitting a single file into multiple class files 30 # Usage: split-class <header file> 31 32 use strict; 33 use File::Copy; 34 use FindBin; 35 use lib $FindBin::Bin; 36 use SpacingHeuristics; 37 38 39 for my $filename (@ARGV) { 40 41 $filename =~ m/^(\w+)\.h$/ or die "Command line args must be .h files.\n"; 42 my $basename = $1; 43 44 open(OLDFILE, "<", $filename) or die "File does not exist: $filename\n"; 45 print "Splitting class $filename.{h,cpp}:\n"; 46 47 my $currentClassName = ""; 48 my $classIndent = ""; 49 my $fileContent = ""; 50 my %classDefs = (); 51 while (my $line = <OLDFILE>) { 52 if ($currentClassName) { 53 $classDefs{$currentClassName} .= $line; 54 if ($line =~ /^$classIndent};\s*$/) { 55 $currentClassName = ""; 56 } 57 } else { 58 if ($line =~ /^(\s*)class\s+(\w+)\s+[^;]*$/) { 59 $classIndent = $1; 60 $currentClassName = $2; 61 $classDefs{$currentClassName} .= $line; 62 $fileContent .= "###CLASS###$currentClassName\n"; 63 } else { 64 $fileContent .= $line; 65 } 66 } 67 } 68 close(OLDFILE); 69 70 if (scalar(keys(%classDefs)) == 1) { # degenerate case 71 my ($classname) = keys(%classDefs); 72 if (!($classname eq $basename)) { 73 print "Skipping $filename, already correctly named.\n"; 74 } else { 75 print "$filename only includes one class, renaming to $classname.h\n"; 76 system("svn rm --force $classname.h") if (-r "$classname.h"); 77 system "svn mv $basename.h $classname.h"; 78 } 79 } else { 80 while (my ($classname, $classDef) = each(%classDefs)) { 81 if (($classname eq $basename)) { 82 print "Skipping $filename, already correctly named.\n"; 83 } else { 84 print "Using SVN to copy $basename.{h,cpp} to $classname.{h,cpp}\n"; 85 86 system("svn rm --force $classname.h") if (-r "$classname.h"); 87 system "svn cp $basename.h $classname.h"; 88 89 system("svn rm --force $classname.cpp") if (-r "$classname.cpp"); 90 system "svn cp $basename.cpp $classname.cpp"; 91 } 92 93 print "Fixing $classname.h as much as possible.\n"; 94 open(NEWHEADER, ">", "$classname.h") or die "File does not exist: $filename\n"; 95 my @lines = split("\n", $fileContent); 96 foreach my $line (@lines) { 97 if ($line =~ /^###CLASS###(\w+)/) { 98 if ($1 eq $classname) { 99 print NEWHEADER $classDef . "\n"; 100 } 101 } else { 102 print NEWHEADER $line . "\n"; 103 } 104 } 105 close(NEWHEADER); 106 107 print "Fixing $classname.cpp as much as possible.\n"; 108 copy("$classname.cpp", "$classname.cpp.original"); 109 open(OLDCPP, "<", "$classname.cpp.original") or die "Failed to copy file for reading: $filename\n"; 110 open(NEWCPP, ">", "$classname.cpp") or die "File does not exist: $filename\n"; 111 my $insideMemberFunction = 0; 112 my $shouldPrintMemberFunction = 0; 113 resetSpacingHeuristics(); 114 while (my $line = <OLDCPP>) { 115 if ($insideMemberFunction) { 116 if ($shouldPrintMemberFunction) { 117 print NEWCPP $line; 118 #setPreviousAllowedLine($line); 119 } else { 120 ignoringLine($line); 121 } 122 if ($line =~ /^}\s*$/) { 123 $insideMemberFunction = 0; 124 } 125 } elsif ($line =~ /$filename/) { 126 print NEWCPP "#include \"config.h\"\n"; 127 print NEWCPP "#include \"$classname.h\"\n"; 128 } elsif ($line =~ /#include/ || $line =~ /#import/) { 129 next; # skip includes, they're generally wrong or unecessary anyway. 130 } else { 131 $line =~ s/DOM:://; 132 $line =~ s/khtml:://; 133 $line =~ s/namespace DOM/namespace WebCore/; 134 $line =~ s/namespace khtml/namespace WebCore/; 135 136 if ($line =~ /^(.*?\s+)?(\*|&)?(\w+)::(~)?\w+\s*\(/) { 137 $insideMemberFunction = 1; 138 $shouldPrintMemberFunction = ($classname eq $3); 139 if ($shouldPrintMemberFunction) { 140 printPendingEmptyLines(*NEWCPP, $line); 141 print NEWCPP $line; 142 } 143 } else { 144 next if isOnlyWhiteSpace($line); 145 next if ($line =~ m/------------/); 146 printPendingEmptyLines(*NEWCPP, $line); 147 applySpacingHeuristicsAndPrint(*NEWCPP, $line); 148 } 149 } 150 } 151 close(NEWCPP); 152 close(OLDCPP); 153 unlink("$classname.cpp.original"); 154 } 155 } 156 157 print "Opening new files...\n"; 158 system("open " . join(".* ", keys(%classDefs)) . ".*"); 159 }