<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[181170] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/181170">181170</a></dd>
<dt>Author</dt> <dd>mitz@apple.com</dd>
<dt>Date</dt> <dd>2015-03-06 10:47:28 -0800 (Fri, 06 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Expose some of the functionality of extract-localizable-strings.pl as a module
https://bugs.webkit.org/show_bug.cgi?id=142038

Reviewed by Sam Weinig.

* LocalizableStrings.pm: Copied from Source/WebCore/extract-localizable-strings.pl.
(setTreatWarningsAsErrors): Added this setter for the variable moved here.
(sawError): Added a getter.
(emitError): Added. Emits the error message and sets $sawError.
(unescapeHexSequence): Moved from extract-localizable-strings.pl and renamed to start with
a lowercase letter.
(keyCollisionCount): Added this getter.
(localizedCount): Added this getter.
(HandleUIString): Moved from extract-localizable-strings.pl and made it increment the
localized string count.
(writeStringsFile): Moved code from extract-localizable-strings.pl into this new subroutine.
(verifyStringsFile): Ditto.

* WebCore.xcodeproj/project.pbxproj: Added LocalizableStrings.pm to the Copy Scripts build
phase.

* extract-localizable-strings.pl:
(emitWarning): Moved to the module.
(UnescapeHexSequence): Ditto.
(HandleUIString): Ditto.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreextractlocalizablestringspl">trunk/Source/WebCore/extract-localizable-strings.pl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreLocalizableStringspm">trunk/Source/WebCore/LocalizableStrings.pm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (181169 => 181170)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-06 18:45:48 UTC (rev 181169)
+++ trunk/Source/WebCore/ChangeLog        2015-03-06 18:47:28 UTC (rev 181170)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2015-03-06  Dan Bernstein  &lt;mitz@apple.com&gt;
+
+        Expose some of the functionality of extract-localizable-strings.pl as a module
+        https://bugs.webkit.org/show_bug.cgi?id=142038
+
+        Reviewed by Sam Weinig.
+
+        * LocalizableStrings.pm: Copied from Source/WebCore/extract-localizable-strings.pl.
+        (setTreatWarningsAsErrors): Added this setter for the variable moved here.
+        (sawError): Added a getter.
+        (emitError): Added. Emits the error message and sets $sawError.
+        (unescapeHexSequence): Moved from extract-localizable-strings.pl and renamed to start with
+        a lowercase letter.
+        (keyCollisionCount): Added this getter.
+        (localizedCount): Added this getter.
+        (HandleUIString): Moved from extract-localizable-strings.pl and made it increment the
+        localized string count.
+        (writeStringsFile): Moved code from extract-localizable-strings.pl into this new subroutine.
+        (verifyStringsFile): Ditto.
+
+        * WebCore.xcodeproj/project.pbxproj: Added LocalizableStrings.pm to the Copy Scripts build
+        phase.
+
+        * extract-localizable-strings.pl:
+        (emitWarning): Moved to the module.
+        (UnescapeHexSequence): Ditto.
+        (HandleUIString): Ditto.
+
</ins><span class="cx"> 2015-03-06  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove unused C++ DOM event handler attribute functions
</span></span></pre></div>
<a id="trunkSourceWebCoreLocalizableStringspm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/LocalizableStrings.pm (0 => 181170)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/LocalizableStrings.pm                                (rev 0)
+++ trunk/Source/WebCore/LocalizableStrings.pm        2015-03-06 18:47:28 UTC (rev 181170)
</span><span class="lines">@@ -0,0 +1,223 @@
</span><ins>+# Copyright (C) 2006, 2007, 2009, 2010, 2013, 2015 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+
+my $treatWarningsAsErrors = 0;
+
+sub setTreatWarningsAsErrors($)
+{
+    ($treatWarningsAsErrors) = @_;
+}
+
+my $sawError = 0;
+
+sub sawError()
+{
+    return $sawError;
+}
+
+sub emitError($$$)
+{
+    my ($file, $line, $message) = @_;
+    print &quot;$file:$line: $message\n&quot;;
+    $sawError = 1;
+}
+
+sub emitWarning($$$)
+{
+    my ($file, $line, $message) = @_;
+    my $prefix = $treatWarningsAsErrors ? &quot;&quot; : &quot;warning: &quot;;
+    print &quot;$file:$line: $prefix$message\n&quot;;
+    $sawError = 1 if $treatWarningsAsErrors;
+}
+
+# Unescapes C language hexadecimal escape sequences.
+sub unescapeHexSequence($)
+{
+    my ($originalStr) = @_;
+
+    my $escapedStr = $originalStr;
+    my $unescapedStr = &quot;&quot;;
+
+    for (;;) {
+        if ($escapedStr =~ s-^\\x([[:xdigit:]]+)--) {
+            if (256 &lt;= hex($1)) {
+                print &quot;Hexadecimal escape sequence out of range: \\x$1\n&quot;;
+                return undef;
+            }
+            $unescapedStr .= pack(&quot;H*&quot;, $1);
+        } elsif ($escapedStr =~ s-^(.)--) {
+            $unescapedStr .= $1;
+        } else {
+            return $unescapedStr;
+        }
+    }
+}
+
+my $keyCollisionCount = 0;
+
+sub keyCollisionCount()
+{
+    return $keyCollisionCount;
+}
+
+my $localizedCount = 0;
+
+sub localizedCount()
+{
+    return $localizedCount;
+}
+
+my %stringByKey;
+my %commentByKey;
+my %fileByKey;
+my %lineByKey;
+
+sub HandleUIString
+{
+    my ($string, $key, $comment, $file, $line) = @_;
+
+    $localizedCount++;
+
+    my $bad = 0;
+    $string = unescapeHexSequence($string);
+    if (!defined($string)) {
+        print &quot;$file:$line: string has an illegal hexadecimal escape sequence\n&quot;;
+        $bad = 1;
+    }
+    $key = unescapeHexSequence($key);
+    if (!defined($key)) {
+        print &quot;$file:$line: key has an illegal hexadecimal escape sequence\n&quot;;
+        $bad = 1;
+    }
+    $comment = unescapeHexSequence($comment);
+    if (!defined($comment)) {
+        print &quot;$file:$line: comment has an illegal hexadecimal escape sequence\n&quot;;
+        $bad = 1;
+    }
+    if (grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $string) {
+        print &quot;$file:$line: string for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
+        $bad = 1;
+    }
+    if ($string ne $key &amp;&amp; grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $key) {
+        print &quot;$file:$line: key has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
+        $bad = 1;
+    }
+    if (grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $comment) {
+        print &quot;$file:$line: comment for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
+        $bad = 1;
+    }
+    if ($bad) {
+        $sawError = 1;
+        return;
+    }
+    
+    if ($stringByKey{$key} &amp;&amp; $stringByKey{$key} ne $string) {
+        emitWarning($file, $line, &quot;encountered the same key, \&quot;$key\&quot;, twice, with different strings&quot;);
+        emitWarning($fileByKey{$key}, $lineByKey{$key}, &quot;previous occurrence&quot;);
+        $keyCollisionCount++;
+        return;
+    }
+    if ($commentByKey{$key} &amp;&amp; $commentByKey{$key} ne $comment) {
+        emitWarning($file, $line, &quot;encountered the same key, \&quot;$key\&quot;, twice, with different comments&quot;);
+        emitWarning($fileByKey{$key}, $lineByKey{$key}, &quot;previous occurrence&quot;);
+        $keyCollisionCount++;
+        return;
+    }
+
+    $fileByKey{$key} = $file;
+    $lineByKey{$key} = $line;
+    $stringByKey{$key} = $string;
+    $commentByKey{$key} = $comment;
+}
+
+sub writeStringsFile($)
+{
+    my ($file) = @_;
+
+    my $localizedStrings = &quot;&quot;;
+
+    for my $key (sort keys %commentByKey) {
+        $localizedStrings .= &quot;/* $commentByKey{$key} */\n\&quot;$key\&quot; = \&quot;$stringByKey{$key}\&quot;;\n\n&quot;;
+    }
+
+    # Write out the strings file as UTF-8
+    open STRINGS, &quot;&gt;&quot;, $file or die;
+    print STRINGS $localizedStrings;
+    close STRINGS;
+}
+
+sub verifyStringsFile($)
+{
+    my ($file) = @_;
+
+    open STRINGS, $file or die;
+
+    my $lastComment;
+    my $line;
+    my $sawError;
+
+    while (&lt;STRINGS&gt;) {
+        chomp;
+
+        next if (/^\s*$/);
+
+        if (/^\/\* (.*) \*\/$/) {
+            $lastComment = $1;
+        } elsif (/^&quot;((?:[^\\]|\\[^&quot;])*)&quot;\s*=\s*&quot;((?:[^\\]|\\[^&quot;])*)&quot;;$/) #
+        {
+            my $string = delete $stringByKey{$1};
+            if (!defined $string) {
+                print &quot;$file:$.: unused key \&quot;$1\&quot;\n&quot;;
+                $sawError = 1;
+            } else {
+                if (!($string eq $2)) {
+                    print &quot;$file:$.: unexpected value \&quot;$2\&quot; for key \&quot;$1\&quot;\n&quot;;
+                    print &quot;$fileByKey{$1}:$lineByKey{$1}: expected value \&quot;$string\&quot; defined here\n&quot;;
+                    $sawError = 1;
+                }
+                if (!($lastComment eq $commentByKey{$1})) {
+                    print &quot;$file:$.: unexpected comment /* $lastComment */ for key \&quot;$1\&quot;\n&quot;;
+                    print &quot;$fileByKey{$1}:$lineByKey{$1}: expected comment /* $commentByKey{$1} */ defined here\n&quot;;
+                    $sawError = 1;
+                }
+            }
+        } else {
+            print &quot;$file:$.: line with unexpected format: $_\n&quot;;
+            $sawError = 1;
+        }
+    }
+
+    for my $missing (keys %stringByKey) {
+        print &quot;$fileByKey{$missing}:$lineByKey{$missing}: missing key \&quot;$missing\&quot;\n&quot;;
+        $sawError = 1;
+    }
+
+    if ($sawError) {
+        print &quot;\n$file:0: file is not up to date.\n&quot;;
+        exit 1;
+    }
+}
+
+1;
</ins><span class="cx">Property changes on: trunk/Source/WebCore/LocalizableStrings.pm
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (181169 => 181170)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-03-06 18:45:48 UTC (rev 181169)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-03-06 18:47:28 UTC (rev 181170)
</span><span class="lines">@@ -1369,6 +1369,7 @@
</span><span class="cx">                 37C238221098C84200EF9F72 /* ComplexTextControllerCoreText.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.mm */; };
</span><span class="cx">                 37C28A6810F659CC008C7813 /* TypesettingFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C28A6710F659CC008C7813 /* TypesettingFeatures.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 37C61F0112095C87007A3C67 /* AtomicStringKeyedMRUCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C61F0012095C87007A3C67 /* AtomicStringKeyedMRUCache.h */; };
</span><ins>+                37D456FD1A9A50D8003330A1 /* LocalizableStrings.pm in Copy Scripts */ = {isa = PBXBuildFile; fileRef = 37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */; };
</ins><span class="cx">                 37DDCD9413844FD50008B793 /* MIMEHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDCD9213844FD50008B793 /* MIMEHeader.cpp */; };
</span><span class="cx">                 37DDCD9513844FD50008B793 /* MIMEHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDCD9313844FD50008B793 /* MIMEHeader.h */; };
</span><span class="cx">                 37DDCD9E13844FFA0008B793 /* Archive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDCD9D13844FFA0008B793 /* Archive.cpp */; };
</span><span class="lines">@@ -6958,6 +6959,7 @@
</span><span class="cx">                         dstPath = PrivateHeaders/Scripts;
</span><span class="cx">                         dstSubfolderSpec = 1;
</span><span class="cx">                         files = (
</span><ins>+                                37D456FD1A9A50D8003330A1 /* LocalizableStrings.pm in Copy Scripts */,
</ins><span class="cx">                                 3717D7E817ECC591003C276D /* extract-localizable-strings.pl in Copy Scripts */,
</span><span class="cx">                         );
</span><span class="cx">                         name = &quot;Copy Scripts&quot;;
</span><span class="lines">@@ -8461,6 +8463,7 @@
</span><span class="cx">                 37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ComplexTextControllerCoreText.mm; sourceTree = &quot;&lt;group&gt;&quot;; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
</span><span class="cx">                 37C28A6710F659CC008C7813 /* TypesettingFeatures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypesettingFeatures.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 37C61F0012095C87007A3C67 /* AtomicStringKeyedMRUCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicStringKeyedMRUCache.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = LocalizableStrings.pm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 37DDCD9213844FD50008B793 /* MIMEHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MIMEHeader.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 37DDCD9313844FD50008B793 /* MIMEHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIMEHeader.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 37DDCD9D13844FFA0008B793 /* Archive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Archive.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15630,6 +15633,7 @@
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><span class="cx">                                 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */,
</span><ins>+                                37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */,
</ins><span class="cx">                         );
</span><span class="cx">                         name = Scripts;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span></span></pre></div>
<a id="trunkSourceWebCoreextractlocalizablestringspl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/extract-localizable-strings.pl (181169 => 181170)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/extract-localizable-strings.pl        2015-03-06 18:45:48 UTC (rev 181169)
+++ trunk/Source/WebCore/extract-localizable-strings.pl        2015-03-06 18:47:28 UTC (rev 181170)
</span><span class="lines">@@ -45,11 +45,12 @@
</span><span class="cx"> use strict;
</span><span class="cx"> use File::Compare;
</span><span class="cx"> use File::Copy;
</span><ins>+use FindBin;
</ins><span class="cx"> use Getopt::Long;
</span><ins>+use lib $FindBin::Bin;
+use LocalizableStrings;
</ins><span class="cx"> no warnings 'deprecated';
</span><span class="cx"> 
</span><del>-sub UnescapeHexSequence($);
-
</del><span class="cx"> my %isDebugMacro = ( ASSERT_WITH_MESSAGE =&gt; 1, LOG_ERROR =&gt; 1, ERROR =&gt; 1, NSURL_ERROR =&gt; 1, FATAL =&gt; 1, LOG =&gt; 1, LOG_WARNING =&gt; 1, UI_STRING_LOCALIZE_LATER =&gt; 1, UI_STRING_LOCALIZE_LATER_KEY =&gt; 1, LPCTSTR_UI_STRING_LOCALIZE_LATER =&gt; 1, UNLOCALIZED_STRING =&gt; 1, UNLOCALIZED_LPCTSTR =&gt; 1, dprintf =&gt; 1, NSException =&gt; 1, NSLog =&gt; 1, printf =&gt; 1 );
</span><span class="cx"> 
</span><span class="cx"> my $verify;
</span><span class="lines">@@ -66,6 +67,8 @@
</span><span class="cx"> 
</span><span class="cx"> GetOptions(%options);
</span><span class="cx"> 
</span><ins>+setTreatWarningsAsErrors($treatWarningsAsErrors);
+
</ins><span class="cx"> @ARGV &gt;= 2 or die &quot;Usage: extract-localizable-strings [--verify] [--treat-warnings-as-errors] [--exceptions &lt;exceptions file&gt;] &lt;file to update&gt; [--skip directory | directory]...\nDid you mean to run update-webkit-localizable-strings instead?\n&quot;;
</span><span class="cx"> 
</span><span class="cx"> -f $exceptionsFile or die &quot;Couldn't find exceptions file $exceptionsFile\n&quot; unless !defined $exceptionsFile;
</span><span class="lines">@@ -84,24 +87,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-my $sawError = 0;
-
-my $localizedCount = 0;
-my $keyCollisionCount = 0;
</del><span class="cx"> my $notLocalizedCount = 0;
</span><span class="cx"> my $NSLocalizeCount = 0;
</span><span class="cx"> 
</span><span class="cx"> my %exception;
</span><span class="cx"> my %usedException;
</span><span class="cx"> 
</span><del>-sub emitWarning($$$)
-{
-    my ($file, $line, $message) = @_;
-    my $prefix = $treatWarningsAsErrors ? &quot;&quot; : &quot;warning: &quot;;
-    print &quot;$file:$line: $prefix$message\n&quot;;
-    $sawError = 1 if $treatWarningsAsErrors;
-}
-
</del><span class="cx"> if (defined $exceptionsFile &amp;&amp; open EXCEPTIONS, $exceptionsFile) {
</span><span class="cx">     while (&lt;EXCEPTIONS&gt;) {
</span><span class="cx">         chomp;
</span><span class="lines">@@ -165,8 +156,7 @@
</span><span class="cx">             
</span><span class="cx">             if ($token eq &quot;\&quot;&quot;) {
</span><span class="cx">                 if ($expected and $expected ne &quot;a quoted string&quot;) {
</span><del>-                    print &quot;$file:$.: found a quoted string but expected $expected\n&quot;;
-                    $sawError = 1;
</del><ins>+                    emitError($file, $., &quot;found a quoted string but expected $expected&quot;);
</ins><span class="cx">                     $expected = &quot;&quot;;
</span><span class="cx">                 }
</span><span class="cx">                 if (s-^(([^\\$token]|\\.)*?)$token--) {
</span><span class="lines">@@ -177,8 +167,7 @@
</span><span class="cx">                         $string .= $1;
</span><span class="cx">                     }
</span><span class="cx">                 } else {
</span><del>-                    print &quot;$file:$.: mismatched quotes\n&quot;;
-                    $sawError = 1;
</del><ins>+                    emitError($file, $., &quot;mismatched quotes&quot;);
</ins><span class="cx">                     $_ = &quot;&quot;;
</span><span class="cx">                 }
</span><span class="cx">                 next;
</span><span class="lines">@@ -227,9 +216,8 @@
</span><span class="cx">             $previousToken = $token;
</span><span class="cx"> 
</span><span class="cx">             if ($token =~ /^NSLocalized/ &amp;&amp; $token !~ /NSLocalizedDescriptionKey/ &amp;&amp; $token !~ /NSLocalizedStringFromTableInBundle/ &amp;&amp; $token !~ /NSLocalizedFileSizeDescription/ &amp;&amp; $token !~ /NSLocalizedDescriptionKey/ &amp;&amp; $token !~ /NSLocalizedRecoverySuggestionErrorKey/) {
</span><del>-                print &quot;$file:$.: found a use of an NSLocalized macro ($token); not supported\n&quot;;
</del><ins>+                emitError($file, $., &quot;found a use of an NSLocalized macro ($token); not supported&quot;);
</ins><span class="cx">                 $nestingLevel = 0 if !defined $nestingLevel;
</span><del>-                $sawError = 1;
</del><span class="cx">                 $NSLocalizeCount++;
</span><span class="cx">             } elsif ($token eq &quot;/*&quot;) {
</span><span class="cx">                 if (!s-^.*?\*/--) {
</span><span class="lines">@@ -240,14 +228,12 @@
</span><span class="cx">                 $_ = &quot;&quot;; # Discard the rest of the line
</span><span class="cx">             } elsif ($token eq &quot;'&quot;) {
</span><span class="cx">                 if (!s-([^\\]|\\.)'--) { #' &lt;-- that single quote makes the Project Builder editor less confused
</span><del>-                    print &quot;$file:$.: mismatched single quote\n&quot;;
-                    $sawError = 1;
</del><ins>+                    emitError($file, $., &quot;mismatched single quote&quot;);
</ins><span class="cx">                     $_ = &quot;&quot;;
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 if ($expected and $expected ne $token) {
</span><del>-                    print &quot;$file:$.: found $token but expected $expected\n&quot;;
-                    $sawError = 1;
</del><ins>+                    emitError($file, $., &quot;found $token but expected $expected&quot;);
</ins><span class="cx">                     $expected = &quot;&quot;;
</span><span class="cx">                 }
</span><span class="cx">                 if ($token =~ /(WEB_)?UI_STRING(_KEY)?(_INTERNAL)?$/) {
</span><span class="lines">@@ -269,7 +255,6 @@
</span><span class="cx">                         HandleUIString($UIString, $key, $comment, $file, $macroLine);
</span><span class="cx">                         $macro = &quot;&quot;;
</span><span class="cx">                         $expected = &quot;&quot;;
</span><del>-                        $localizedCount++;
</del><span class="cx">                     }
</span><span class="cx">                 } elsif ($isDebugMacro{$token}) {
</span><span class="cx">                     $nestingLevel = 0 if !defined $nestingLevel;
</span><span class="lines">@@ -282,99 +267,14 @@
</span><span class="cx">     goto handleString if defined $string;
</span><span class="cx">     
</span><span class="cx">     if ($expected) {
</span><del>-        print &quot;$file: reached end of file but expected $expected\n&quot;;
-        $sawError = 1;
</del><ins>+        emitError($file, 0, &quot;reached end of file but expected $expected&quot;);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     close SOURCE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-# Unescapes C language hexadecimal escape sequences.
-sub UnescapeHexSequence($)
-{
-    my ($originalStr) = @_;
</del><ins>+print &quot;\n&quot; if sawError() || $notLocalizedCount || $NSLocalizeCount;
</ins><span class="cx"> 
</span><del>-    my $escapedStr = $originalStr;
-    my $unescapedStr = &quot;&quot;;
-
-    for (;;) {
-        if ($escapedStr =~ s-^\\x([[:xdigit:]]+)--) {
-            if (256 &lt;= hex($1)) {
-                print &quot;Hexadecimal escape sequence out of range: \\x$1\n&quot;;
-                return undef;
-            }
-            $unescapedStr .= pack(&quot;H*&quot;, $1);
-        } elsif ($escapedStr =~ s-^(.)--) {
-            $unescapedStr .= $1;
-        } else {
-            return $unescapedStr;
-        }
-    }
-}
-
-my %stringByKey;
-my %commentByKey;
-my %fileByKey;
-my %lineByKey;
-
-sub HandleUIString
-{
-    my ($string, $key, $comment, $file, $line) = @_;
-
-    my $bad = 0;
-    $string = UnescapeHexSequence($string);
-    if (!defined($string)) {
-        print &quot;$file:$line: string has an illegal hexadecimal escape sequence\n&quot;;
-        $bad = 1;
-    }
-    $key = UnescapeHexSequence($key);
-    if (!defined($key)) {
-        print &quot;$file:$line: key has an illegal hexadecimal escape sequence\n&quot;;
-        $bad = 1;
-    }
-    $comment = UnescapeHexSequence($comment);
-    if (!defined($comment)) {
-        print &quot;$file:$line: comment has an illegal hexadecimal escape sequence\n&quot;;
-        $bad = 1;
-    }
-    if (grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $string) {
-        print &quot;$file:$line: string for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
-        $bad = 1;
-    }
-    if ($string ne $key &amp;&amp; grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $key) {
-        print &quot;$file:$line: key has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
-        $bad = 1;
-    }
-    if (grep { $_ == 0xFFFD } unpack &quot;U*&quot;, $comment) {
-        print &quot;$file:$line: comment for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n&quot;;
-        $bad = 1;
-    }
-    if ($bad) {
-        $sawError = 1;
-        return;
-    }
-    
-    if ($stringByKey{$key} &amp;&amp; $stringByKey{$key} ne $string) {
-        emitWarning($file, $line, &quot;encountered the same key, \&quot;$key\&quot;, twice, with different strings&quot;);
-        emitWarning($fileByKey{$key}, $lineByKey{$key}, &quot;previous occurrence&quot;);
-        $keyCollisionCount++;
-        return;
-    }
-    if ($commentByKey{$key} &amp;&amp; $commentByKey{$key} ne $comment) {
-        emitWarning($file, $line, &quot;encountered the same key, \&quot;$key\&quot;, twice, with different comments&quot;);
-        emitWarning($fileByKey{$key}, $lineByKey{$key}, &quot;previous occurrence&quot;);
-        $keyCollisionCount++;
-        return;
-    }
-
-    $fileByKey{$key} = $file;
-    $lineByKey{$key} = $line;
-    $stringByKey{$key} = $string;
-    $commentByKey{$key} = $comment;
-}
-
-print &quot;\n&quot; if $sawError || $notLocalizedCount || $NSLocalizeCount;
-
</del><span class="cx"> my @unusedExceptions = sort grep { !$usedException{$_} } keys %exception;
</span><span class="cx"> if (@unusedExceptions) {
</span><span class="cx">     for my $unused (@unusedExceptions) {
</span><span class="lines">@@ -383,30 +283,21 @@
</span><span class="cx">     print &quot;\n&quot;;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-print &quot;$localizedCount localizable strings\n&quot; if $localizedCount;
-print &quot;$keyCollisionCount key collisions\n&quot; if $keyCollisionCount;
</del><ins>+print localizedCount() . &quot; localizable strings\n&quot; if localizedCount();
+print keyCollisionCount() . &quot; key collisions\n&quot; if keyCollisionCount();
</ins><span class="cx"> print &quot;$notLocalizedCount strings not marked for localization\n&quot; if $notLocalizedCount;
</span><span class="cx"> print &quot;$NSLocalizeCount uses of NSLocalize\n&quot; if $NSLocalizeCount;
</span><span class="cx"> print scalar(@unusedExceptions), &quot; unused exceptions\n&quot; if @unusedExceptions;
</span><span class="cx"> 
</span><del>-if ($sawError) {
</del><ins>+if (sawError()) {
</ins><span class="cx">     print &quot;\nErrors encountered. Exiting without writing to $fileToUpdate.\n&quot;;
</span><span class="cx">     exit 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-my $localizedStrings = &quot;&quot;;
-
-for my $key (sort keys %commentByKey) {
-    $localizedStrings .= &quot;/* $commentByKey{$key} */\n\&quot;$key\&quot; = \&quot;$stringByKey{$key}\&quot;;\n\n&quot;;
-}
-
</del><span class="cx"> if (-e &quot;$fileToUpdate&quot;) {
</span><span class="cx">     if (!$verify) {
</span><del>-        # Write out the strings file as UTF-8
</del><span class="cx">         my $temporaryFile = &quot;$fileToUpdate.updated&quot;;
</span><del>-        open STRINGS, &quot;&gt;&quot;, $temporaryFile or die;
-        print STRINGS $localizedStrings;
-        close STRINGS;
</del><ins>+        writeStringsFile($temporaryFile);
</ins><span class="cx"> 
</span><span class="cx">         # Avoid updating the target file's modification time if the contents have not changed.
</span><span class="cx">         if (compare($temporaryFile, $fileToUpdate)) {
</span><span class="lines">@@ -415,51 +306,7 @@
</span><span class="cx">             unlink $temporaryFile;
</span><span class="cx">         }
</span><span class="cx">     } else {
</span><del>-        open STRINGS, $fileToUpdate or die;
-
-        my $lastComment;
-        my $line;
-
-        while (&lt;STRINGS&gt;) {
-            chomp;
-
-            next if (/^\s*$/);
-
-            if (/^\/\* (.*) \*\/$/) {
-                $lastComment = $1;
-            } elsif (/^&quot;((?:[^\\]|\\[^&quot;])*)&quot;\s*=\s*&quot;((?:[^\\]|\\[^&quot;])*)&quot;;$/) #
-            {
-                my $string = delete $stringByKey{$1};
-                if (!defined $string) {
-                    print &quot;$fileToUpdate:$.: unused key \&quot;$1\&quot;\n&quot;;
-                    $sawError = 1;
-                } else {
-                    if (!($string eq $2)) {
-                        print &quot;$fileToUpdate:$.: unexpected value \&quot;$2\&quot; for key \&quot;$1\&quot;\n&quot;;
-                        print &quot;$fileByKey{$1}:$lineByKey{$1}: expected value \&quot;$string\&quot; defined here\n&quot;;
-                        $sawError = 1;
-                    }
-                    if (!($lastComment eq $commentByKey{$1})) {
-                        print &quot;$fileToUpdate:$.: unexpected comment /* $lastComment */ for key \&quot;$1\&quot;\n&quot;;
-                        print &quot;$fileByKey{$1}:$lineByKey{$1}: expected comment /* $commentByKey{$1} */ defined here\n&quot;;
-                        $sawError = 1;
-                    }
-                }
-            } else {
-                print &quot;$fileToUpdate:$.: line with unexpected format: $_\n&quot;;
-                $sawError = 1;
-            }
-        }
-
-        for my $missing (keys %stringByKey) {
-            print &quot;$fileByKey{$missing}:$lineByKey{$missing}: missing key \&quot;$missing\&quot;\n&quot;;
-            $sawError = 1;
-        }
-
-        if ($sawError) {
-            print &quot;\n$fileToUpdate:0: file is not up to date.\n&quot;;
-            exit 1;
-        }
</del><ins>+        verifyStringsFile($fileToUpdate);
</ins><span class="cx">     }
</span><span class="cx"> } else {
</span><span class="cx">     print &quot;error: $fileToUpdate does not exist\n&quot;;
</span></span></pre>
</div>
</div>

</body>
</html>