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
28 # error definitions to output
30 ErrorsToCreatDescFor
= []
32 # some lookup dictionaries
41 self
.err_define
= None
45 def escapeString( input ):
46 output
= input.replace('"','\\"')
47 output
= output
.replace("\\<","\\\\<")
48 output
= output
.replace('\t',"")
51 def transformErrorName( 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
62 def parseErrorDescriptions( file_contents
, isWinError
):
64 for line
in file_contents
:
65 content
= line
.strip().split(None,1)
66 # start new error definition ?
67 if line
.startswith("0x"):
69 newError
.err_code
= int(content
[0],0)
70 # escape the usual suspects
72 newError
.err_string
= escapeString(content
[1])
73 newError
.linenum
= count
74 newError
.isWinError
= isWinError
75 Errors
.append(newError
)
78 print "Error parsing file as line %d"%count
81 if err
.err_define
== None:
82 err
.err_define
= transformErrorName(content
[0])
85 desc
= escapeString(line
.strip())
87 if err
.err_string
== "":
90 err
.err_string
= err
.err_string
+ " " + desc
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)
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)
105 code
= int(error_code_string
,0)
110 def parseHeaderFile(file_contents
):
112 for line
in file_contents
:
113 contents
= line
.strip().split(None,2)
114 err_code_string
= 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
)
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
129 print "warning: failed to process line[%d] ->%s<-"%(count
,line
)
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
)
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
:
172 def processErrorDescription(err_def_with_desc
):
173 print "processing error descriptions...."
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
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
)
191 ErrorsToUse
.append(err
)
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.
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]
223 print "usage: %s headerfile winerrorfile existing_short_descs"%(sys
.argv
[0])
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
)
237 out_file
= open(sourcefile_name
,"w")
238 generateSourceFile(out_file
)
241 if __name__
== '__main__':