--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright (c) 2003-2004,2006,2008,2012,2014 Apple Inc. All Rights Reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+#
+# generateErrStrings.pl - create error strings files from the Security header files
+#
+# Usage:
+#
+# perl generateErrStrings.pl <GENDEBUGSTRS?> <NAME_OF_STRINGS_FILE> <input files>
+#
+# Currently supported files are SecBase.h, SecureTransport.h,cssmapple.h,
+# cssmerr.h and Authorization.h. These are used by:
+#
+# void cssmPerror(const char *how, CSSM_RETURN error);
+#
+# which is in SecBase.cpp.
+#
+# Paths of input files:
+#
+# ./libsecurity_authorization/lib/Authorization.h
+# ./libsecurity_cssm/lib/cssmapple.h
+# ./libsecurity_cssm/lib/cssmerr.h
+# ./libsecurity_keychain/lib/SecBase.h
+# ./libsecurity_ssl/lib/SecureTransport.h
+#
+# Sample run:
+#
+# perl generateErrStrings.pl "YES" "SecErrorMessages.strings" Authorization.h SecBase.h \
+# cssmapple.h cssmerr.h SecureTransport.h
+#
+# Input to script: header file(s) containing enum declarations
+# Output: C++ program with one cout statement per decl
+#
+# The input headers are scanned for enums containing error numbers and
+# optional comments. Only certain prefixes for the identifiers in the
+# enums are considered, to avoid non-error message type defines. See
+# the line in the file with CSSM_ERRCODE for acceptable prefixes.
+#
+# There are three styles of comments that this script parses:
+#
+# Style A [see /System/Library/Frameworks/Security.framework/Headers/SecBase.h]:
+#
+# errSSLProtocol = -9800, /* SSL protocol error */
+#
+# Style B [see /System/Library/Frameworks/Security.framework/Headers/cssmapple.h]:
+#
+# /* a code signature match failed */
+# CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2,
+#
+# Style C [see /System/Library/Frameworks/Security.framework/Headers/cssmerr.h]:
+#
+# CSSM_CSSM_BASE_CSSM_ERROR =
+# CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10,
+# CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1,
+#
+# Style A has the comment after the comment. Style has the comment before the value,
+# and Style C has no comment. In cases where both Style A and B apply, the
+# comment at the end of the line is used.
+#
+# The final output after the generated Objective-C++ program is run looks like:
+#
+# /* errSSLProtocol */
+# "-9800" = "SSL protocol error";
+#
+# /* errSSLNegotiation */
+# "-9801" = "Cipher Suite negotiation failure";
+#
+# The appropriate byte order marker for UTF-16 is written to the start of the file.
+# Note that the list of errors must be numerically unique across all input files,
+# or the strings file will be invalid. Comments in "Style B" may span multiple lines.
+# C++ style comments are not supported. Double quotes in a comment are hardened with
+# "\" in the output.
+#
+# The English versions of the error messages can be seen with:
+#
+# cat /System/Library/Frameworks/Security.framework/Resources/English.lproj/SecErrorMessages.strings
+#
+# find -H -X -x . -name "*.h" -print0 2>/dev/null | xargs -0 grep -ri err
+# -----------------------------------------------------------------------------------
+
+# Style questions:
+# - what should I make PROGNAME?
+# - should I use a special call to make the temp file in the .mm file?
+#
+
+#use strict;
+#use warnings;
+
+die "Usage: $0 <gendebug> <tmpdir> <.strings file> <list of headers>\n" if ($#ARGV < 3);
+
+$GENDEBUGSTRINGS=$ARGV[0]; # If "YES", include all strings & don't localize
+$TMPDIR=$ARGV[1]; # temporary directory for program compile, link, run
+$TARGETSTR=$ARGV[2]; # path of .strings file, e.g.
+ # ${DERIVED_SRC}/English.lproj/SecErrorMessages.strings
+@INPUTFILES=@ARGV[3 .. 9999]; # list of input files
+
+$#INPUTFILES = $#ARGV - 3; # truncate to actual number of files
+
+print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n";
+$PROGNAME="${TMPDIR}/generateErrStrings.mm";
+open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!";
+select PROGRAM;
+
+printAdditionalIncludes();
+printInputIncludes();
+printMainProgram();
+
+# -----------------------------------------------------------------------------------
+# Parse error headers and build array of all relevant lines
+open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files";
+$/="\};"; #We set the section termination string - very important
+processInput();
+close(ERR);
+# -----------------------------------------------------------------------------------
+
+printTrailer();
+select STDOUT;
+close PROGRAM;
+
+compileLinkAndRun();
+
+# 4: Done!
+exit;
+
+# -----------------------------------------------------------------------------------
+# Subroutines
+# -----------------------------------------------------------------------------------
+
+sub processInput
+{
+ # 3: Read input, process each line, output it.
+ while ( $line = <ERR>)
+ {
+ ($enum) = ($line =~ /\n\s*enum\s*{\s*([^}]*)};/);
+ while ($enum ne '') #basic filter for badly formed enums
+ {
+ #Drop leading whitespace
+ $enum =~ s/^\s+//;
+ # print "A:", $enum,"\n";
+ ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%);
+ if ($leadingcomment ne '')
+ {
+ $enum = substr($enum, length($leadingcomment));
+ $leadingcomment = substr($leadingcomment, 2); # drop leading "/*"
+ $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/"
+ $leadingcomment = cleanupComment($leadingcomment);
+ }
+ next if ($enum eq ''); #basic filter for badly formed enums
+
+ # Check for C++ style comments at start of line
+ if ($enum =~ /\s*(\/\/)/)
+ {
+ #Drop everything before the end of line
+ $enum =~ s/[^\n]*[\n]*//;
+ next;
+ }
+ ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/);
+
+# print "identifier: ", $identifier,"\n" if ($identifier ne '');
+
+ #Drop everything before the comma
+ $enum =~ s/[^,]*,//;
+
+ # Now look for trailing comment. We only consider them
+ # trailing if they come before the end of the line
+ ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//);
+ # ($trailingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%);
+ $trailingcomment = cleanupComment($trailingcomment);
+
+ #Drop everything before the end of line
+ $enum =~ s/[^\n]*[\n]*//;
+ # print "B:", $enum,"\n";
+ # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n";
+ # print "===========================================\n";
+
+ writecomment($leadingcomment, $identifier, $trailingcomment);
+ }
+ }
+}
+
+sub writecomment
+{
+ # Leading comment, id, trailing comment
+ # To aid localizers, we will not output a line with no comment
+ #
+ # Output is e.g.
+ # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess
+ # << "\" = \"The operation completed successfully.\"\n" << endl;
+
+ my($mylc,$myid,$mytc) = @_;
+ if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/)
+ {
+ $errormessage = '';
+ if ($mytc ne '')
+ { $errormessage = $mytc; }
+ elsif ($mylc ne '')
+ { $errormessage = $mylc; }
+ elsif ($GENDEBUGSTRINGS eq "YES")
+ { $errormessage = $myid; }
+
+ if ($errormessage ne '')
+ {
+ print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << ";
+ print $myid, " << \"\\\" = \\\"";
+ print $errormessage, "\\\";\\n\" << endl;\n";
+ }
+ }
+};
+
+
+sub printAdditionalIncludes
+{
+ #This uses the "here" construct to dump out lines verbatim
+ print <<"AdditionalIncludes";
+
+#include <iostream>
+#include <fstream>
+#include <CoreFoundation/CoreFoundation.h>
+#include <Foundation/Foundation.h>
+
+using namespace std;
+AdditionalIncludes
+}
+
+sub printInputIncludes
+{
+ #Now "#include" each of the input files
+ print "\n#include \"$_\"" foreach @INPUTFILES;
+ print "\n";
+}
+
+sub printMainProgram
+{
+ #Output the main part of the program using the "here" construct
+ print <<"MAINPROGRAM";
+
+void writeStrings(const char *stringsFileName);
+void createStringsTemp();
+
+int main (int argc, char * const argv[])
+{
+ const char *stringsFileName = NULL;
+
+ if (argc == 2)
+ stringsFileName = argv[1];
+ else
+ if (argc == 1)
+ stringsFileName = "SecErrorMessages.strings";
+ else
+ return -1;
+
+ cout << "Strings file to create: " << stringsFileName << endl;
+ createStringsTemp();
+ writeStrings(stringsFileName);
+}
+
+void writeStrings(const char *stringsFileName)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"];
+ NSData *rawstrings = [fh readDataToEndOfFile];
+ UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8);
+ NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding];
+
+ if (instring)
+ {
+ NSString *path = [NSString stringWithUTF8String:stringsFileName];
+ NSFileManager *fm = [NSFileManager defaultManager];
+ if ([fm fileExistsAtPath:path])
+ [fm removeFileAtPath:path handler:nil];
+ BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil];
+ NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path];
+ [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]];
+ }
+
+ [pool release];
+}
+
+void createStringsTemp()
+{
+ ofstream tmp("generateErrStrings.tmp") ;
+
+MAINPROGRAM
+}
+
+sub cleanupComment
+{
+ my $comment = shift @_;
+# print "A:",$comment,"\n";
+ if ($comment ne '')
+ {
+ $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one
+ $comment =~ s/^\s+//; # Drop leading whitespace
+ $comment =~ s/\s+$//; # Drop trailing whitespace
+ $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf)
+ }
+# print "B:",$comment,"\n";
+ $comment;
+}
+
+sub printTrailer
+{
+ print " tmp.close();\n";
+ print "}\n";
+}
+
+sub compileLinkAndRun
+{
+ $status = system( <<"MAINPROGRAM");
+(cd ${TMPDIR} ; /usr/bin/cc -x objective-c++ -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -g -O0 -Wreturn-type -fmessage-length=0 -F$ENV{'BUILT_PRODUCTS_DIR'} -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/Headers -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/PrivateHeaders -c generateErrStrings.mm -o generateErrStrings.o)
+MAINPROGRAM
+ die "$compile exited funny: $?" unless $status == 0;
+
+ $status = system( <<"LINKERSTEP");
+(cd ${TMPDIR} ; /usr/bin/clang++ -o generateErrStrings generateErrStrings.o -framework Foundation )
+LINKERSTEP
+ die "$linker exited funny: $?" unless $status == 0;
+
+ $status = system( <<"RUNSTEP");
+(cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR )
+RUNSTEP
+ die "$built program exited funny: $?" unless $status == 0;
+}
+