]> git.saurik.com Git - apple/security.git/blame - OSX/lib/generateErrStrings.pl
Security-58286.31.2.tar.gz
[apple/security.git] / OSX / lib / generateErrStrings.pl
CommitLineData
563f4f96
A
1#!/usr/bin/perl
2#
d8f41ccd 3# Copyright (c) 2003-2004,2006,2008,2012,2014 Apple Inc. All Rights Reserved.
563f4f96
A
4#
5# @APPLE_LICENSE_HEADER_START@
6#
7# This file contains Original Code and/or Modifications of Original Code
8# as defined in and that are subject to the Apple Public Source License
9# Version 2.0 (the 'License'). You may not use this file except in
10# compliance with the License. Please obtain a copy of the License at
11# http://www.opensource.apple.com/apsl/ and read it before using this
12# file.
13#
14# The Original Code and all software distributed under the License are
15# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19# Please see the License for the specific language governing rights and
20# limitations under the License.
21#
22# @APPLE_LICENSE_HEADER_END@
23#
f380ce78 24# generateErrStrings.pl - create error strings files from the Security header files
563f4f96
A
25#
26# Usage:
563f4f96 27#
f380ce78
A
28# perl generateErrStrings.pl <GENDEBUGSTRS?> <NAME_OF_STRINGS_FILE> <input files>
29#
30# Currently supported files are SecBase.h, SecureTransport.h,cssmapple.h,
31# cssmerr.h and Authorization.h. These are used by:
32#
33# void cssmPerror(const char *how, CSSM_RETURN error);
34#
35# which is in SecBase.cpp.
36#
37# Paths of input files:
38#
39# ./libsecurity_authorization/lib/Authorization.h
40# ./libsecurity_cssm/lib/cssmapple.h
41# ./libsecurity_cssm/lib/cssmerr.h
42# ./libsecurity_keychain/lib/SecBase.h
43# ./libsecurity_ssl/lib/SecureTransport.h
44#
45# Sample run:
46#
47# perl generateErrStrings.pl "YES" "SecErrorMessages.strings" Authorization.h SecBase.h \
48# cssmapple.h cssmerr.h SecureTransport.h
49#
50# Input to script: header file(s) containing enum declarations
51# Output: C++ program with one cout statement per decl
52#
53# The input headers are scanned for enums containing error numbers and
54# optional comments. Only certain prefixes for the identifiers in the
55# enums are considered, to avoid non-error message type defines. See
56# the line in the file with CSSM_ERRCODE for acceptable prefixes.
563f4f96 57#
f380ce78 58# There are three styles of comments that this script parses:
563f4f96 59#
f380ce78 60# Style A [see /System/Library/Frameworks/Security.framework/Headers/SecBase.h]:
563f4f96
A
61#
62# errSSLProtocol = -9800, /* SSL protocol error */
563f4f96 63#
f380ce78
A
64# Style B [see /System/Library/Frameworks/Security.framework/Headers/cssmapple.h]:
65#
66# /* a code signature match failed */
67# CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2,
68#
69# Style C [see /System/Library/Frameworks/Security.framework/Headers/cssmerr.h]:
70#
71# CSSM_CSSM_BASE_CSSM_ERROR =
72# CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10,
73# CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1,
74#
75# Style A has the comment after the comment. Style has the comment before the value,
76# and Style C has no comment. In cases where both Style A and B apply, the
77# comment at the end of the line is used.
78#
79# The final output after the generated Objective-C++ program is run looks like:
563f4f96
A
80#
81# /* errSSLProtocol */
82# "-9800" = "SSL protocol error";
83#
84# /* errSSLNegotiation */
85# "-9801" = "Cipher Suite negotiation failure";
86#
f380ce78
A
87# The appropriate byte order marker for UTF-16 is written to the start of the file.
88# Note that the list of errors must be numerically unique across all input files,
89# or the strings file will be invalid. Comments in "Style B" may span multiple lines.
993ca007
A
90# C++ style comments are not supported. Double quotes in a comment are hardened with
91# "\" in the output.
f380ce78
A
92#
93# The English versions of the error messages can be seen with:
563f4f96 94#
f380ce78
A
95# cat /System/Library/Frameworks/Security.framework/Resources/English.lproj/SecErrorMessages.strings
96#
97# find -H -X -x . -name "*.h" -print0 2>/dev/null | xargs -0 grep -ri err
98# -----------------------------------------------------------------------------------
563f4f96 99
f380ce78
A
100# Style questions:
101# - what should I make PROGNAME?
102# - should I use a special call to make the temp file in the .mm file?
103#
563f4f96 104
f380ce78
A
105#use strict;
106#use warnings;
563f4f96 107
f380ce78
A
108die "Usage: $0 <gendebug> <tmpdir> <.strings file> <list of headers>\n" if ($#ARGV < 3);
109
110$GENDEBUGSTRINGS=$ARGV[0]; # If "YES", include all strings & don't localize
111$TMPDIR=$ARGV[1]; # temporary directory for program compile, link, run
112$TARGETSTR=$ARGV[2]; # path of .strings file, e.g.
113 # ${DERIVED_SRC}/English.lproj/SecErrorMessages.strings
114@INPUTFILES=@ARGV[3 .. 9999]; # list of input files
115
116$#INPUTFILES = $#ARGV - 3; # truncate to actual number of files
117
118print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n";
119$PROGNAME="${TMPDIR}/generateErrStrings.mm";
120open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!";
121select PROGRAM;
122
123printAdditionalIncludes();
124printInputIncludes();
125printMainProgram();
126
127# -----------------------------------------------------------------------------------
128# Parse error headers and build array of all relevant lines
129open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files";
130$/="\};"; #We set the section termination string - very important
131processInput();
563f4f96 132close(ERR);
f380ce78 133# -----------------------------------------------------------------------------------
563f4f96 134
f380ce78
A
135printTrailer();
136select STDOUT;
137close PROGRAM;
563f4f96 138
f380ce78 139compileLinkAndRun();
563f4f96 140
f380ce78
A
141# 4: Done!
142exit;
143
144# -----------------------------------------------------------------------------------
145# Subroutines
146# -----------------------------------------------------------------------------------
147
148sub processInput
149{
150 # 3: Read input, process each line, output it.
151 while ( $line = <ERR>)
152 {
5c19dc3a 153 ($enum) = ($line =~ /\n\s*(?:enum|CF_ENUM\(OSStatus\))\s*{\s*([^}]*)};/);
f380ce78
A
154 while ($enum ne '') #basic filter for badly formed enums
155 {
156 #Drop leading whitespace
157 $enum =~ s/^\s+//;
158 # print "A:", $enum,"\n";
159 ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%);
160 if ($leadingcomment ne '')
161 {
162 $enum = substr($enum, length($leadingcomment));
163 $leadingcomment = substr($leadingcomment, 2); # drop leading "/*"
164 $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/"
165 $leadingcomment = cleanupComment($leadingcomment);
166 }
167 next if ($enum eq ''); #basic filter for badly formed enums
168
169 # Check for C++ style comments at start of line
170 if ($enum =~ /\s*(\/\/)/)
171 {
172 #Drop everything before the end of line
173 $enum =~ s/[^\n]*[\n]*//;
174 next;
175 }
176 ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/);
177
178# print "identifier: ", $identifier,"\n" if ($identifier ne '');
179
866f8763
A
180 #Drop everything before the comma, end of line or trailing comment
181 $enum =~ s/[^,]*(,|\n|(\/\*))//;
f380ce78
A
182
183 # Now look for trailing comment. We only consider them
184 # trailing if they come before the end of the line
185 ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//);
f380ce78
A
186 $trailingcomment = cleanupComment($trailingcomment);
187
188 #Drop everything before the end of line
189 $enum =~ s/[^\n]*[\n]*//;
190 # print "B:", $enum,"\n";
191 # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n";
192 # print "===========================================\n";
193
194 writecomment($leadingcomment, $identifier, $trailingcomment);
195 }
196 }
197}
198
199sub writecomment
563f4f96 200{
f380ce78
A
201 # Leading comment, id, trailing comment
202 # To aid localizers, we will not output a line with no comment
203 #
204 # Output is e.g.
205 # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess
206 # << "\" = \"The operation completed successfully.\"\n" << endl;
207
208 my($mylc,$myid,$mytc) = @_;
209 if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/)
210 {
211 $errormessage = '';
212 if ($mytc ne '')
213 { $errormessage = $mytc; }
214 elsif ($mylc ne '')
215 { $errormessage = $mylc; }
216 elsif ($GENDEBUGSTRINGS eq "YES")
217 { $errormessage = $myid; }
218
219 if ($errormessage ne '')
220 {
221 print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << ";
222 print $myid, " << \"\\\" = \\\"";
223 print $errormessage, "\\\";\\n\" << endl;\n";
224 }
225 }
563f4f96 226};
563f4f96 227
f380ce78
A
228
229sub printAdditionalIncludes
230{
231 #This uses the "here" construct to dump out lines verbatim
232 print <<"AdditionalIncludes";
563f4f96 233
f380ce78
A
234#include <iostream>
235#include <fstream>
236#include <CoreFoundation/CoreFoundation.h>
237#include <Foundation/Foundation.h>
563f4f96 238
f380ce78
A
239using namespace std;
240AdditionalIncludes
563f4f96 241}
563f4f96 242
f380ce78
A
243sub printInputIncludes
244{
245 #Now "#include" each of the input files
246 print "\n#include \"$_\"" foreach @INPUTFILES;
247 print "\n";
248}
249
250sub printMainProgram
251{
252 #Output the main part of the program using the "here" construct
253 print <<"MAINPROGRAM";
254
255void writeStrings(const char *stringsFileName);
256void createStringsTemp();
257
258int main (int argc, char * const argv[])
259{
260 const char *stringsFileName = NULL;
261
262 if (argc == 2)
263 stringsFileName = argv[1];
264 else
265 if (argc == 1)
266 stringsFileName = "SecErrorMessages.strings";
267 else
268 return -1;
269
270 cout << "Strings file to create: " << stringsFileName << endl;
271 createStringsTemp();
272 writeStrings(stringsFileName);
273}
274
275void writeStrings(const char *stringsFileName)
276{
277 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
278 NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"];
279 NSData *rawstrings = [fh readDataToEndOfFile];
280 UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8);
281 NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding];
282
283 if (instring)
284 {
285 NSString *path = [NSString stringWithUTF8String:stringsFileName];
286 NSFileManager *fm = [NSFileManager defaultManager];
287 if ([fm fileExistsAtPath:path])
5c19dc3a 288 [fm removeItemAtPath:path error:NULL];
f380ce78
A
289 BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil];
290 NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path];
291 [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]];
292 }
293
294 [pool release];
295}
296
297void createStringsTemp()
298{
299 ofstream tmp("generateErrStrings.tmp") ;
300
301MAINPROGRAM
302}
303
304sub cleanupComment
305{
306 my $comment = shift @_;
307# print "A:",$comment,"\n";
308 if ($comment ne '')
309 {
310 $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one
311 $comment =~ s/^\s+//; # Drop leading whitespace
312 $comment =~ s/\s+$//; # Drop trailing whitespace
993ca007 313 $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf)
f380ce78
A
314 }
315# print "B:",$comment,"\n";
316 $comment;
317}
318
319sub printTrailer
320{
321 print " tmp.close();\n";
322 print "}\n";
323}
324
325sub compileLinkAndRun
326{
327 $status = system( <<"MAINPROGRAM");
328(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)
329MAINPROGRAM
330 die "$compile exited funny: $?" unless $status == 0;
331
332 $status = system( <<"LINKERSTEP");
427c49bc 333(cd ${TMPDIR} ; /usr/bin/clang++ -o generateErrStrings generateErrStrings.o -framework Foundation )
f380ce78
A
334LINKERSTEP
335 die "$linker exited funny: $?" unless $status == 0;
336
337 $status = system( <<"RUNSTEP");
338(cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR )
339RUNSTEP
340 die "$built program exited funny: $?" unless $status == 0;
341}
563f4f96 342