]>
Commit | Line | Data |
---|---|---|
563f4f96 A |
1 | #!/usr/bin/perl |
2 | # | |
3 | # Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. | |
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 |
108 | die "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 | ||
118 | print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n"; | |
119 | $PROGNAME="${TMPDIR}/generateErrStrings.mm"; | |
120 | open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!"; | |
121 | select PROGRAM; | |
122 | ||
123 | printAdditionalIncludes(); | |
124 | printInputIncludes(); | |
125 | printMainProgram(); | |
126 | ||
127 | # ----------------------------------------------------------------------------------- | |
128 | # Parse error headers and build array of all relevant lines | |
129 | open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; | |
130 | $/="\};"; #We set the section termination string - very important | |
131 | processInput(); | |
563f4f96 | 132 | close(ERR); |
f380ce78 | 133 | # ----------------------------------------------------------------------------------- |
563f4f96 | 134 | |
f380ce78 A |
135 | printTrailer(); |
136 | select STDOUT; | |
137 | close PROGRAM; | |
563f4f96 | 138 | |
f380ce78 | 139 | compileLinkAndRun(); |
563f4f96 | 140 | |
f380ce78 A |
141 | # 4: Done! |
142 | exit; | |
143 | ||
144 | # ----------------------------------------------------------------------------------- | |
145 | # Subroutines | |
146 | # ----------------------------------------------------------------------------------- | |
147 | ||
148 | sub processInput | |
149 | { | |
150 | # 3: Read input, process each line, output it. | |
151 | while ( $line = <ERR>) | |
152 | { | |
153 | ($enum) = ($line =~ /\n\s*enum\s*{\s*([^}]*)};/); | |
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 | ||
180 | #Drop everything before the comma | |
181 | $enum =~ s/[^,]*,//; | |
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]*\/\*((.)*)?\*\//); | |
186 | # ($trailingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); | |
187 | $trailingcomment = cleanupComment($trailingcomment); | |
188 | ||
189 | #Drop everything before the end of line | |
190 | $enum =~ s/[^\n]*[\n]*//; | |
191 | # print "B:", $enum,"\n"; | |
192 | # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n"; | |
193 | # print "===========================================\n"; | |
194 | ||
195 | writecomment($leadingcomment, $identifier, $trailingcomment); | |
196 | } | |
197 | } | |
198 | } | |
199 | ||
200 | sub writecomment | |
563f4f96 | 201 | { |
f380ce78 A |
202 | # Leading comment, id, trailing comment |
203 | # To aid localizers, we will not output a line with no comment | |
204 | # | |
205 | # Output is e.g. | |
206 | # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess | |
207 | # << "\" = \"The operation completed successfully.\"\n" << endl; | |
208 | ||
209 | my($mylc,$myid,$mytc) = @_; | |
210 | if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/) | |
211 | { | |
212 | $errormessage = ''; | |
213 | if ($mytc ne '') | |
214 | { $errormessage = $mytc; } | |
215 | elsif ($mylc ne '') | |
216 | { $errormessage = $mylc; } | |
217 | elsif ($GENDEBUGSTRINGS eq "YES") | |
218 | { $errormessage = $myid; } | |
219 | ||
220 | if ($errormessage ne '') | |
221 | { | |
222 | print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << "; | |
223 | print $myid, " << \"\\\" = \\\""; | |
224 | print $errormessage, "\\\";\\n\" << endl;\n"; | |
225 | } | |
226 | } | |
563f4f96 | 227 | }; |
563f4f96 | 228 | |
f380ce78 A |
229 | |
230 | sub printAdditionalIncludes | |
231 | { | |
232 | #This uses the "here" construct to dump out lines verbatim | |
233 | print <<"AdditionalIncludes"; | |
563f4f96 | 234 | |
f380ce78 A |
235 | #include <iostream> |
236 | #include <fstream> | |
237 | #include <CoreFoundation/CoreFoundation.h> | |
238 | #include <Foundation/Foundation.h> | |
563f4f96 | 239 | |
f380ce78 A |
240 | using namespace std; |
241 | AdditionalIncludes | |
563f4f96 | 242 | } |
563f4f96 | 243 | |
f380ce78 A |
244 | sub printInputIncludes |
245 | { | |
246 | #Now "#include" each of the input files | |
247 | print "\n#include \"$_\"" foreach @INPUTFILES; | |
248 | print "\n"; | |
249 | } | |
250 | ||
251 | sub printMainProgram | |
252 | { | |
253 | #Output the main part of the program using the "here" construct | |
254 | print <<"MAINPROGRAM"; | |
255 | ||
256 | void writeStrings(const char *stringsFileName); | |
257 | void createStringsTemp(); | |
258 | ||
259 | int main (int argc, char * const argv[]) | |
260 | { | |
261 | const char *stringsFileName = NULL; | |
262 | ||
263 | if (argc == 2) | |
264 | stringsFileName = argv[1]; | |
265 | else | |
266 | if (argc == 1) | |
267 | stringsFileName = "SecErrorMessages.strings"; | |
268 | else | |
269 | return -1; | |
270 | ||
271 | cout << "Strings file to create: " << stringsFileName << endl; | |
272 | createStringsTemp(); | |
273 | writeStrings(stringsFileName); | |
274 | } | |
275 | ||
276 | void writeStrings(const char *stringsFileName) | |
277 | { | |
278 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
279 | NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"]; | |
280 | NSData *rawstrings = [fh readDataToEndOfFile]; | |
281 | UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8); | |
282 | NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding]; | |
283 | ||
284 | if (instring) | |
285 | { | |
286 | NSString *path = [NSString stringWithUTF8String:stringsFileName]; | |
287 | NSFileManager *fm = [NSFileManager defaultManager]; | |
288 | if ([fm fileExistsAtPath:path]) | |
289 | [fm removeFileAtPath:path handler:nil]; | |
290 | BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil]; | |
291 | NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path]; | |
292 | [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]]; | |
293 | } | |
294 | ||
295 | [pool release]; | |
296 | } | |
297 | ||
298 | void createStringsTemp() | |
299 | { | |
300 | ofstream tmp("generateErrStrings.tmp") ; | |
301 | ||
302 | MAINPROGRAM | |
303 | } | |
304 | ||
305 | sub cleanupComment | |
306 | { | |
307 | my $comment = shift @_; | |
308 | # print "A:",$comment,"\n"; | |
309 | if ($comment ne '') | |
310 | { | |
311 | $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one | |
312 | $comment =~ s/^\s+//; # Drop leading whitespace | |
313 | $comment =~ s/\s+$//; # Drop trailing whitespace | |
993ca007 | 314 | $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf) |
f380ce78 A |
315 | } |
316 | # print "B:",$comment,"\n"; | |
317 | $comment; | |
318 | } | |
319 | ||
320 | sub printTrailer | |
321 | { | |
322 | print " tmp.close();\n"; | |
323 | print "}\n"; | |
324 | } | |
325 | ||
326 | sub compileLinkAndRun | |
327 | { | |
328 | $status = system( <<"MAINPROGRAM"); | |
329 | (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) | |
330 | MAINPROGRAM | |
331 | die "$compile exited funny: $?" unless $status == 0; | |
332 | ||
333 | $status = system( <<"LINKERSTEP"); | |
334 | (cd ${TMPDIR} ; /usr/bin/g++ -o generateErrStrings generateErrStrings.o -framework Foundation ) | |
335 | LINKERSTEP | |
336 | die "$linker exited funny: $?" unless $status == 0; | |
337 | ||
338 | $status = system( <<"RUNSTEP"); | |
339 | (cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR ) | |
340 | RUNSTEP | |
341 | die "$built program exited funny: $?" unless $status == 0; | |
342 | } | |
563f4f96 | 343 |