ldb:wscript: remove allow_warnings=True for ldb_sample
[Samba.git] / source4 / scripting / bin / gen_ntstatus.py
blob3625ad72cac13edb383b856e19c461bfbcb735c9
1 #!/usr/bin/env python
4 # Unix SMB/CIFS implementation.
6 # HRESULT Error definitions
8 # Copyright (C) Noel Power <noel.power@suse.com> 2014
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 import sys, os.path, io, string
26 # parsed error data
27 Errors = []
28 # error definitions to output
29 ErrorsToUse = []
30 ErrorsToCreatDescFor = []
32 # some lookup dictionaries
33 DefineToErrCode = {};
34 ErrCodeToDefine = {};
36 # error data model
37 class ErrorDef:
39 def __init__(self):
40 self.err_code = None
41 self.err_define = None
42 self.err_string = ""
43 self.linenum = ""
45 def escapeString( input ):
46 output = input.replace('"','\\"')
47 output = output.replace("\\<","\\\\<")
48 output = output.replace('\t',"")
49 return output
51 def transformErrorName( error_name ):
52 new_name = error_name
53 if error_name.startswith("STATUS_"):
54 error_name = error_name.replace("STATUS_","",1)
55 elif error_name.startswith("RPC_NT_"):
56 error_name = error_name.replace("RPC_NT_","RPC_",1)
57 elif error_name.startswith("EPT_NT_"):
58 error_name = error_name.replace("EPT_NT_","EPT_",1)
59 new_name = "NT_STATUS_" + error_name
60 return new_name
62 def parseErrorDescriptions( file_contents, isWinError ):
63 count = 0
64 for line in file_contents:
65 content = line.strip().split(None,1)
66 # start new error definition ?
67 if line.startswith("0x"):
68 newError = ErrorDef()
69 newError.err_code = int(content[0],0)
70 # escape the usual suspects
71 if len(content) > 1:
72 newError.err_string = escapeString(content[1])
73 newError.linenum = count
74 newError.isWinError = isWinError
75 Errors.append(newError)
76 else:
77 if len(Errors) == 0:
78 print "Error parsing file as line %d"%count
79 sys.exit()
80 err = Errors[-1]
81 if err.err_define == None:
82 err.err_define = transformErrorName(content[0])
83 else:
84 if len(content) > 0:
85 desc = escapeString(line.strip())
86 if len(desc):
87 if err.err_string == "":
88 err.err_string = desc
89 else:
90 err.err_string = err.err_string + " " + desc
91 count = count + 1
92 print "parsed %d lines generated %d error definitions"%(count,len(Errors))
94 def parseErrCodeString(error_code_string):
95 # we could develop this more and *really* parse it but realistically
96 # we are only interested in NT_STATUS( mask | code ) or NT_STATUS( code )
97 parts = error_code_string.split('|',1)
98 code = None
99 try:
100 if len(parts) > 1:
101 if len(parts) > 2: #something weird, better warn
102 print "warning something weird unexpected errorcode format ->%s<-"%error_code_string
103 code = int(parts[0],0) | int(parts[1],0)
104 else:
105 code = int(error_code_string,0)
106 except:
107 pass
108 return code
110 def parseHeaderFile(file_contents):
111 count = 0
112 for line in file_contents:
113 contents = line.strip().split(None,2)
114 err_code_string = None
115 err_code = None
117 if len(contents) > 2:
118 if contents[0] == "#define" and contents[2].startswith("NT_STATUS("):
119 # hairy parsing of lines like
120 # "#define SOMETHING NT_STATUS( num1 | num2 )" etc...
121 err_code_string = contents[2].split('(')[1].split(')')[0]
122 err_code = parseErrCodeString( err_code_string )
123 if err_code != None:
124 const_define = contents[1]
125 # print "%s 0x%x"%(const_define, err_code)
126 DefineToErrCode[const_define] = err_code
127 ErrCodeToDefine[err_code] = const_define
128 else:
129 print "warning: failed to process line[%d] ->%s<-"%(count,line)
130 count = count + 1
131 print "read %d error declarations from header file"%len(ErrCodeToDefine)
133 def generateHeaderFile(out_file):
134 out_file.write("\n\n")
135 out_file.write("/*\n")
136 out_file.write(" * New descriptions for new errors generated from\n")
137 out_file.write(" * [MS-ERREF] http://msdn.microsoft.com/en-us/library/cc704588.aspx\n")
138 out_file.write(" */\n\n")
139 for err in ErrorsToUse:
140 line = "#define {0:49} NT_STATUS(0x{1:08X})\n".format(err.err_define ,err.err_code)
141 out_file.write(line)
144 def generateSourceFile(out_file):
145 out_file.write("/*\n")
146 out_file.write(" * New descriptions for existing errors generated from\n")
147 out_file.write(" * [MS-ERREF] http://msdn.microsoft.com/en-us/library/cc704588.aspx\n")
148 out_file.write(" */\n")
149 for err in ErrorsToCreatDescFor:
150 out_file.write(" { N_(\"%s\"), %s },\n"%(err.err_string, err.err_define))
151 out_file.write("\n\n")
152 out_file.write("/*\n")
153 out_file.write(" * New descriptions for new errors generated from\n")
154 out_file.write(" * [MS-ERREF] http://msdn.microsoft.com/en-us/library/cc704588.aspx\n")
155 out_file.write(" */\n")
156 for err in ErrorsToUse:
157 out_file.write(" { N_(\"%s\"), %s },\n"%(err.err_string, err.err_define))
158 out_file.write("\n\n");
159 out_file.write("/*\n")
160 out_file.write(" * New descriptions for new errors generated from\n")
161 out_file.write(" * [MS-ERREF] http://msdn.microsoft.com/en-us/library/cc704588.aspx\n")
162 out_file.write(" */\n")
163 for err in ErrorsToUse:
164 out_file.write(" { \"%s\", %s },\n"%(err.err_define, err.err_define))
166 def def_in_list(define, err_def_with_desc):
167 for item in err_def_with_desc:
168 if item.strip() == define:
169 return True
170 return False
172 def processErrorDescription(err_def_with_desc):
173 print "processing error descriptions...."
174 count = 0
175 for err in Errors:
176 # do we have an error with this error code already ?
177 if ErrCodeToDefine.has_key(err.err_code):
178 already_has_desc = def_in_list(ErrCodeToDefine[err.err_code], err_def_with_desc)
179 # no 'full' error description for this error code so create a new
180 # one
181 if already_has_desc == False:
182 # synthesise a new Error object to create desc from
183 new_error = ErrorDef()
184 new_error.err_define = ErrCodeToDefine[err.err_code]
185 new_error.err_code = err.err_code
186 new_error.err_string = err.err_string
187 new_error.linenum = err.linenum
188 ErrorsToCreatDescFor.append(new_error)
189 count = count + 1
190 else:
191 ErrorsToUse.append(err)
192 if count > 0:
193 print "skipped %d existing definitions"%count
194 print "imported %d new error definitions"%(len(ErrorsToUse))
195 print "created %d new error descriptions for existing errors"%(len(ErrorsToCreatDescFor))
197 # Very simple script to generate files ntstatus.c & ntstatus.h, these
198 # files contain generated content used to add to the existing content
199 # of files nterr.c & ntstatus.h.
200 # The script takes 3 inputs
201 # 1. location of the existing ntstatus.h (which is used to build a list of
202 # existing error defines
203 # 2. a text file, format which is very simple and is just the content of a
204 # html table ( such as that found in
205 # http://msdn.microsoft.com/en-us/library/cc231200.aspx ) copied and
206 # pasted into a text file
207 # 3. finally a text file containing names of the error defines (1 per line)
208 # that already are in ntstatus.h/nterr.c but that only have the 'short'
209 # error description ( short error description is where the description is
210 # the name of the error itself e.g. "NT_STATUS_SUCCESS" etc.
212 def main ():
213 input_file1 = None;
214 input_file2 = None;
215 filename = "ntstatus"
216 headerfile_name = filename + ".h"
217 sourcefile_name = filename + ".c"
218 if len(sys.argv) > 3:
219 input_file1 = sys.argv[1]
220 input_file2 = sys.argv[2]
221 input_file3 = sys.argv[3]
222 else:
223 print "usage: %s headerfile winerrorfile existing_short_descs"%(sys.argv[0])
224 sys.exit()
226 # read in the data
227 file_contents = open(input_file1,"r")
228 parseHeaderFile(file_contents)
229 file_contents = open(input_file2,"r")
230 parseErrorDescriptions(file_contents, False)
231 file_contents = open(input_file3,"r")
232 has_already_desc = file_contents.readlines()
233 processErrorDescription(has_already_desc)
234 out_file = open(headerfile_name,"w")
235 generateHeaderFile(out_file)
236 out_file.close()
237 out_file = open(sourcefile_name,"w")
238 generateSourceFile(out_file)
239 out_file.close()
241 if __name__ == '__main__':
243 main()