From fb13eb7db84e93d3791d0674d82923d5f168530e Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Thu, 15 Oct 2009 11:06:08 +0200 Subject: s4:w32err_code.py script - put it under "scripting/bin" I think this is a better location for this script. Since the subdirectory "script" of "source4" contains only scripts for "make install" and "make uninstall". --- source4/script/w32err_code.py | 361 ----------------------------------- source4/scripting/bin/w32err_code.py | 361 +++++++++++++++++++++++++++++++++++ 2 files changed, 361 insertions(+), 361 deletions(-) delete mode 100755 source4/script/w32err_code.py create mode 100755 source4/scripting/bin/w32err_code.py (limited to 'source4') diff --git a/source4/script/w32err_code.py b/source4/script/w32err_code.py deleted file mode 100755 index cad6f6ecc9..0000000000 --- a/source4/script/w32err_code.py +++ /dev/null @@ -1,361 +0,0 @@ -#!/usr/bin/python - -# Unix SMB/CIFS implementation. -# Copyright (C) Kamen Mazdrashki 2009 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -"""Import generete werror.h/doserr.c files from WSPP HTML""" - -import re -import os -import sys -import urllib -import pprint -from xml.dom import minidom -from optparse import OptionParser, OptionGroup - -_wspp_werror_url = 'http://msdn.microsoft.com/en-us/library/cc231199%28PROT.10%29.aspx' - -class WerrorHtmlParser(object): - """ - Parses HTML from WSPP documentation generating dictionary of - dictionaries with following keys: - - "err_hex" - hex number (as string) - - "err_name" - error name - - "err_desc" - error long description - For the key of returned dictionary err_hex is used, - i.e. "hex-error-code-str" => {error dictionary object} - """ - - ERROR_PREFIX = ['ERROR_', 'NERR_', 'FRS_', 'RPC_', 'EPT_', 'OR_', 'WAIT_TIMEOUT'] - ERROR_REPLACE = ['ERROR_'] - - def __init__(self, opt): - self.opt = opt - self._errors_skipped = [] - pass - - def _is_error_code_name(self, err_name): - for pref in self.ERROR_PREFIX: - if err_name.startswith(pref): - return True - return False - - def _make_werr_name(self, err_name): - err_name = err_name.upper() - for pref in self.ERROR_REPLACE: - if err_name.startswith(pref): - return err_name.replace(pref, 'WERR_', 1) - return 'WERR_' + err_name - - def parse_url(self, url): - errors = {} - html = self._load_url(url) - - # let minidom to parse the tree, should be: - # table -> tr -> td - # p -> [hex code, br, error code] - # p -> [description] - table_node = minidom.parseString(html) - for row_node in table_node.getElementsByTagName("tr"): - # verify we got right number of td elements - td_nodes = row_node.getElementsByTagName('td') - if len(td_nodes) != 2: - continue - # now get the real data - p_nodes = row_node.getElementsByTagName('p') - if len(p_nodes) != 2: continue - if len(p_nodes[0].childNodes) != 3: continue - if len(p_nodes[1].childNodes) != 1: continue - err_hex = str(p_nodes[0].childNodes[0].nodeValue) - err_name = str(p_nodes[0].childNodes[2].nodeValue) - err_desc = p_nodes[1].childNodes[0].nodeValue.encode('utf-8') - err_desc = err_desc.replace('"', '\\"').replace("\'", "\\'") - # do some checking - if not err_hex.startswith('0x'): continue - if not self._is_error_code_name(err_name): - self._errors_skipped.append("%s - %s - %d" % (err_name, err_hex, int(err_hex, 16))) - continue - # create entry - err_name = self._make_werr_name(err_name) - err_def = {'err_hex': err_hex, - 'err_name': err_name, - 'err_desc': err_desc, - 'code': int(err_hex, 16)} - errors[err_def['code']] = err_def - - # print skipped errors - if self.opt.print_skipped and len(self._errors_skipped): - print "\nErrors skipped during HTML parsing:" - pprint.pprint(self._errors_skipped) - print "\n" - - return errors - - def _load_url(self, url): - html_str = "" - try: - fp = urllib.urlopen(url) - for line in fp: - html_str += line.strip() - fp.close() - except IOError, e: - print "error loading url: " + e.strerror - pass - - # currently ERROR codes are rendered as table - # locate table chunk with ERROR_SUCCESS - html = [x for x in html_str.split('') - if pos == -1: - return ''; - html = html[:pos] + '
' - - # html clean up - html = re.sub(r']*>(.*?)', r'\1', html) - - return html - - -class WerrorGenerator(object): - """ - provides methods to generate parts of werror.h and doserr.c files - """ - - FNAME_WERRORS = 'w32errors.lst' - FNAME_WERROR_DEFS = 'werror_defs.h' - FNAME_DOSERR_DEFS = 'doserr_defs.c' - FNAME_DOSERR_DESC = 'doserr_desc.c' - - def __init__(self, opt): - self.opt = opt - self._out_dir = opt.out_dir - pass - - def _open_out_file(self, fname): - fname = os.path.join(self._out_dir, fname) - return open(fname, "w") - - def _gen_werrors_list(self, errors): - """uses 'errors' dictionary to display list of Win32 Errors""" - - fp = self._open_out_file(self.FNAME_WERRORS) - for err_code in sorted(errors.keys()): - err_name = errors[err_code]['err_name'] - fp.write(err_name) - fp.write("\n") - fp.close() - - def _gen_werror_defs(self, errors): - """uses 'errors' dictionary to generate werror.h file""" - - fp = self._open_out_file(self.FNAME_WERROR_DEFS) - for err_code in sorted(errors.keys()): - err_name = errors[err_code]['err_name'] - err_hex = errors[err_code]['err_hex'] - fp.write('#define %s\tW_ERROR(%s)' % (err_name, err_hex)) - fp.write("\n") - fp.close() - - def _gen_doserr_defs(self, errors): - """uses 'errors' dictionary to generate defines in doserr.c file""" - - fp = self._open_out_file(self.FNAME_DOSERR_DEFS) - for err_code in sorted(errors.keys()): - err_name = errors[err_code]['err_name'] - fp.write('\t{ "%s", %s },' % (err_name, err_name)) - fp.write("\n") - fp.close() - - def _gen_doserr_descriptions(self, errors): - """uses 'errors' dictionary to generate descriptions in doserr.c file""" - - fp = self._open_out_file(self.FNAME_DOSERR_DESC) - for err_code in sorted(errors.keys()): - err_name = errors[err_code]['err_name'] - fp.write('\t{ %s, "%s" },' % (err_name, errors[err_code]['err_desc'])) - fp.write("\n") - fp.close() - - def _lookup_error_by_name(self, err_name, defined_errors): - for err in defined_errors.itervalues(): - if err['err_name'] == err_name: - return err - return None - - def _filter_errors(self, errors, defined_errors): - """ - returns tuple (new_erros, diff_code_errors, diff_name_errors) - new_errors - dictionary of errors not in defined_errors - diff_code_errors - list of errors found in defined_errors - but with different value - diff_name_errors - list of errors found with same code in - defined_errors, but with different name - Most critical is diff_code_errors list to be empty! - """ - new_errors = {} - diff_code_errors = [] - diff_name_errors = [] - for err_def in errors.itervalues(): - add_error = True - # try get defined error by code - if defined_errors.has_key(err_def['code']): - old_err = defined_errors[err_def['code']] - if err_def['err_name'] != old_err['err_name']: - warning = {'msg': 'New and Old errors has different error names', - 'err_new': err_def, - 'err_old': old_err} - diff_name_errors.append(warning) - - # sanity check for errors with same name but different values - old_err = self._lookup_error_by_name(err_def['err_name'], defined_errors) - if old_err: - if err_def['code'] != old_err['code']: - warning = {'msg': 'New and Old error defs has different error value', - 'err_new': err_def, - 'err_old': old_err} - diff_code_errors.append(warning) - # exclude error already defined with same name - add_error = False - # do add the error in new_errors if everything is fine - if add_error: - new_errors[err_def['code']] = err_def - pass - return (new_errors, diff_code_errors, diff_name_errors) - - def generate(self, errors): - # load already defined error codes - werr_parser = WerrorParser(self.opt) - (defined_errors, - no_value_errors) = werr_parser.load_err_codes(self.opt.werror_file) - if not defined_errors: - print "\nUnable to load existing errors file: %s" % self.opt.werror_file - sys.exit(1) - if self.opt.verbose and len(no_value_errors): - print "\nWarning: there are errors defines using macro value:" - pprint.pprint(no_value_errors) - print "" - # filter generated error codes - (new_errors, - diff_code_errors, - diff_name_errors) = self._filter_errors(errors, defined_errors) - if diff_code_errors: - print("\nFound %d errors with same names but different error values! Aborting." - % len(diff_code_errors)) - pprint.pprint(diff_code_errors) - sys.exit(2) - - if diff_name_errors: - print("\nFound %d errors with same values but different names (should be normal)" - % len(diff_name_errors)) - pprint.pprint(diff_name_errors) - - # finally generate output files - self._gen_werror_defs(new_errors) - self._gen_doserr_defs(new_errors) - self._gen_werrors_list(errors) - self._gen_doserr_descriptions(errors) - pass - -class WerrorParser(object): - """ - Parses errors defined in werror.h file - """ - - def __init__(self, opt): - self.opt = opt - pass - - def _parse_werror_line(self, line): - m = re.match('#define[ \t]*(.*?)[ \t]*W_ERROR\((.*?)\)', line) - if not m or (len(m.groups()) != 2): - return None - if len(m.group(1)) == 0: - return None - if str(m.group(2)).startswith('0x'): - err_code = int(m.group(2), 16) - elif m.group(2).isdigit(): - err_code = int(m.group(2)) - else: - self.err_no_values.append(line) - return None - return {'err_name': str(m.group(1)), - 'err_hex': "0x%08X" % err_code, - 'code': err_code} - pass - - def load_err_codes(self, fname): - """ - Returns tuple of: - dictionary of "hex_err_code" => {code, name} - "hex_err_code" is string - "code" is int value for the error - list of errors that was ignored for some reason - """ - # reset internal variables - self.err_no_values = [] - err_codes = {} - fp = open(fname) - for line in fp.readlines(): - err_def = self._parse_werror_line(line) - if err_def: - err_codes[err_def['code']] = err_def - fp.close(); - return (err_codes, self.err_no_values) - - - -def _generate_files(opt): - parser = WerrorHtmlParser(opt) - errors = parser.parse_url(opt.url) - - out = WerrorGenerator(opt) - out.generate(errors) - pass - - -if __name__ == '__main__': - _cur_dir = os.path.abspath(os.path.dirname(__file__)) - opt_parser = OptionParser(usage="usage: %prog [options]", version="%prog 0.3") - opt_group = OptionGroup(opt_parser, "Main options") - opt_group.add_option("--url", dest="url", - default=_wspp_werror_url, - help="url for w32 error codes html - may be local file") - opt_group.add_option("--out", dest="out_dir", - default=_cur_dir, - help="output dir for generated files") - opt_group.add_option("--werror", dest="werror_file", - default=os.path.join(_cur_dir, 'werror.h'), - help="path to werror.h file") - opt_group.add_option("--print_skipped", - action="store_true", dest="print_skipped", default=False, - help="print errors skipped during HTML parsing") - opt_group.add_option("-q", "--quiet", - action="store_false", dest="verbose", default=True, - help="don't print warnings to stdout") - - opt_parser.add_option_group(opt_group) - - (options, args) = opt_parser.parse_args() - - # add some options to be used internally - options.err_defs_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_WERROR_DEFS) - options.dos_defs_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_DOSERR_DEFS) - options.dos_desc_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_DOSERR_DESC) - - # check options - _generate_files(options) diff --git a/source4/scripting/bin/w32err_code.py b/source4/scripting/bin/w32err_code.py new file mode 100755 index 0000000000..cad6f6ecc9 --- /dev/null +++ b/source4/scripting/bin/w32err_code.py @@ -0,0 +1,361 @@ +#!/usr/bin/python + +# Unix SMB/CIFS implementation. +# Copyright (C) Kamen Mazdrashki 2009 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +"""Import generete werror.h/doserr.c files from WSPP HTML""" + +import re +import os +import sys +import urllib +import pprint +from xml.dom import minidom +from optparse import OptionParser, OptionGroup + +_wspp_werror_url = 'http://msdn.microsoft.com/en-us/library/cc231199%28PROT.10%29.aspx' + +class WerrorHtmlParser(object): + """ + Parses HTML from WSPP documentation generating dictionary of + dictionaries with following keys: + - "err_hex" - hex number (as string) + - "err_name" - error name + - "err_desc" - error long description + For the key of returned dictionary err_hex is used, + i.e. "hex-error-code-str" => {error dictionary object} + """ + + ERROR_PREFIX = ['ERROR_', 'NERR_', 'FRS_', 'RPC_', 'EPT_', 'OR_', 'WAIT_TIMEOUT'] + ERROR_REPLACE = ['ERROR_'] + + def __init__(self, opt): + self.opt = opt + self._errors_skipped = [] + pass + + def _is_error_code_name(self, err_name): + for pref in self.ERROR_PREFIX: + if err_name.startswith(pref): + return True + return False + + def _make_werr_name(self, err_name): + err_name = err_name.upper() + for pref in self.ERROR_REPLACE: + if err_name.startswith(pref): + return err_name.replace(pref, 'WERR_', 1) + return 'WERR_' + err_name + + def parse_url(self, url): + errors = {} + html = self._load_url(url) + + # let minidom to parse the tree, should be: + # table -> tr -> td + # p -> [hex code, br, error code] + # p -> [description] + table_node = minidom.parseString(html) + for row_node in table_node.getElementsByTagName("tr"): + # verify we got right number of td elements + td_nodes = row_node.getElementsByTagName('td') + if len(td_nodes) != 2: + continue + # now get the real data + p_nodes = row_node.getElementsByTagName('p') + if len(p_nodes) != 2: continue + if len(p_nodes[0].childNodes) != 3: continue + if len(p_nodes[1].childNodes) != 1: continue + err_hex = str(p_nodes[0].childNodes[0].nodeValue) + err_name = str(p_nodes[0].childNodes[2].nodeValue) + err_desc = p_nodes[1].childNodes[0].nodeValue.encode('utf-8') + err_desc = err_desc.replace('"', '\\"').replace("\'", "\\'") + # do some checking + if not err_hex.startswith('0x'): continue + if not self._is_error_code_name(err_name): + self._errors_skipped.append("%s - %s - %d" % (err_name, err_hex, int(err_hex, 16))) + continue + # create entry + err_name = self._make_werr_name(err_name) + err_def = {'err_hex': err_hex, + 'err_name': err_name, + 'err_desc': err_desc, + 'code': int(err_hex, 16)} + errors[err_def['code']] = err_def + + # print skipped errors + if self.opt.print_skipped and len(self._errors_skipped): + print "\nErrors skipped during HTML parsing:" + pprint.pprint(self._errors_skipped) + print "\n" + + return errors + + def _load_url(self, url): + html_str = "" + try: + fp = urllib.urlopen(url) + for line in fp: + html_str += line.strip() + fp.close() + except IOError, e: + print "error loading url: " + e.strerror + pass + + # currently ERROR codes are rendered as table + # locate table chunk with ERROR_SUCCESS + html = [x for x in html_str.split('') + if pos == -1: + return ''; + html = html[:pos] + '
' + + # html clean up + html = re.sub(r']*>(.*?)', r'\1', html) + + return html + + +class WerrorGenerator(object): + """ + provides methods to generate parts of werror.h and doserr.c files + """ + + FNAME_WERRORS = 'w32errors.lst' + FNAME_WERROR_DEFS = 'werror_defs.h' + FNAME_DOSERR_DEFS = 'doserr_defs.c' + FNAME_DOSERR_DESC = 'doserr_desc.c' + + def __init__(self, opt): + self.opt = opt + self._out_dir = opt.out_dir + pass + + def _open_out_file(self, fname): + fname = os.path.join(self._out_dir, fname) + return open(fname, "w") + + def _gen_werrors_list(self, errors): + """uses 'errors' dictionary to display list of Win32 Errors""" + + fp = self._open_out_file(self.FNAME_WERRORS) + for err_code in sorted(errors.keys()): + err_name = errors[err_code]['err_name'] + fp.write(err_name) + fp.write("\n") + fp.close() + + def _gen_werror_defs(self, errors): + """uses 'errors' dictionary to generate werror.h file""" + + fp = self._open_out_file(self.FNAME_WERROR_DEFS) + for err_code in sorted(errors.keys()): + err_name = errors[err_code]['err_name'] + err_hex = errors[err_code]['err_hex'] + fp.write('#define %s\tW_ERROR(%s)' % (err_name, err_hex)) + fp.write("\n") + fp.close() + + def _gen_doserr_defs(self, errors): + """uses 'errors' dictionary to generate defines in doserr.c file""" + + fp = self._open_out_file(self.FNAME_DOSERR_DEFS) + for err_code in sorted(errors.keys()): + err_name = errors[err_code]['err_name'] + fp.write('\t{ "%s", %s },' % (err_name, err_name)) + fp.write("\n") + fp.close() + + def _gen_doserr_descriptions(self, errors): + """uses 'errors' dictionary to generate descriptions in doserr.c file""" + + fp = self._open_out_file(self.FNAME_DOSERR_DESC) + for err_code in sorted(errors.keys()): + err_name = errors[err_code]['err_name'] + fp.write('\t{ %s, "%s" },' % (err_name, errors[err_code]['err_desc'])) + fp.write("\n") + fp.close() + + def _lookup_error_by_name(self, err_name, defined_errors): + for err in defined_errors.itervalues(): + if err['err_name'] == err_name: + return err + return None + + def _filter_errors(self, errors, defined_errors): + """ + returns tuple (new_erros, diff_code_errors, diff_name_errors) + new_errors - dictionary of errors not in defined_errors + diff_code_errors - list of errors found in defined_errors + but with different value + diff_name_errors - list of errors found with same code in + defined_errors, but with different name + Most critical is diff_code_errors list to be empty! + """ + new_errors = {} + diff_code_errors = [] + diff_name_errors = [] + for err_def in errors.itervalues(): + add_error = True + # try get defined error by code + if defined_errors.has_key(err_def['code']): + old_err = defined_errors[err_def['code']] + if err_def['err_name'] != old_err['err_name']: + warning = {'msg': 'New and Old errors has different error names', + 'err_new': err_def, + 'err_old': old_err} + diff_name_errors.append(warning) + + # sanity check for errors with same name but different values + old_err = self._lookup_error_by_name(err_def['err_name'], defined_errors) + if old_err: + if err_def['code'] != old_err['code']: + warning = {'msg': 'New and Old error defs has different error value', + 'err_new': err_def, + 'err_old': old_err} + diff_code_errors.append(warning) + # exclude error already defined with same name + add_error = False + # do add the error in new_errors if everything is fine + if add_error: + new_errors[err_def['code']] = err_def + pass + return (new_errors, diff_code_errors, diff_name_errors) + + def generate(self, errors): + # load already defined error codes + werr_parser = WerrorParser(self.opt) + (defined_errors, + no_value_errors) = werr_parser.load_err_codes(self.opt.werror_file) + if not defined_errors: + print "\nUnable to load existing errors file: %s" % self.opt.werror_file + sys.exit(1) + if self.opt.verbose and len(no_value_errors): + print "\nWarning: there are errors defines using macro value:" + pprint.pprint(no_value_errors) + print "" + # filter generated error codes + (new_errors, + diff_code_errors, + diff_name_errors) = self._filter_errors(errors, defined_errors) + if diff_code_errors: + print("\nFound %d errors with same names but different error values! Aborting." + % len(diff_code_errors)) + pprint.pprint(diff_code_errors) + sys.exit(2) + + if diff_name_errors: + print("\nFound %d errors with same values but different names (should be normal)" + % len(diff_name_errors)) + pprint.pprint(diff_name_errors) + + # finally generate output files + self._gen_werror_defs(new_errors) + self._gen_doserr_defs(new_errors) + self._gen_werrors_list(errors) + self._gen_doserr_descriptions(errors) + pass + +class WerrorParser(object): + """ + Parses errors defined in werror.h file + """ + + def __init__(self, opt): + self.opt = opt + pass + + def _parse_werror_line(self, line): + m = re.match('#define[ \t]*(.*?)[ \t]*W_ERROR\((.*?)\)', line) + if not m or (len(m.groups()) != 2): + return None + if len(m.group(1)) == 0: + return None + if str(m.group(2)).startswith('0x'): + err_code = int(m.group(2), 16) + elif m.group(2).isdigit(): + err_code = int(m.group(2)) + else: + self.err_no_values.append(line) + return None + return {'err_name': str(m.group(1)), + 'err_hex': "0x%08X" % err_code, + 'code': err_code} + pass + + def load_err_codes(self, fname): + """ + Returns tuple of: + dictionary of "hex_err_code" => {code, name} + "hex_err_code" is string + "code" is int value for the error + list of errors that was ignored for some reason + """ + # reset internal variables + self.err_no_values = [] + err_codes = {} + fp = open(fname) + for line in fp.readlines(): + err_def = self._parse_werror_line(line) + if err_def: + err_codes[err_def['code']] = err_def + fp.close(); + return (err_codes, self.err_no_values) + + + +def _generate_files(opt): + parser = WerrorHtmlParser(opt) + errors = parser.parse_url(opt.url) + + out = WerrorGenerator(opt) + out.generate(errors) + pass + + +if __name__ == '__main__': + _cur_dir = os.path.abspath(os.path.dirname(__file__)) + opt_parser = OptionParser(usage="usage: %prog [options]", version="%prog 0.3") + opt_group = OptionGroup(opt_parser, "Main options") + opt_group.add_option("--url", dest="url", + default=_wspp_werror_url, + help="url for w32 error codes html - may be local file") + opt_group.add_option("--out", dest="out_dir", + default=_cur_dir, + help="output dir for generated files") + opt_group.add_option("--werror", dest="werror_file", + default=os.path.join(_cur_dir, 'werror.h'), + help="path to werror.h file") + opt_group.add_option("--print_skipped", + action="store_true", dest="print_skipped", default=False, + help="print errors skipped during HTML parsing") + opt_group.add_option("-q", "--quiet", + action="store_false", dest="verbose", default=True, + help="don't print warnings to stdout") + + opt_parser.add_option_group(opt_group) + + (options, args) = opt_parser.parse_args() + + # add some options to be used internally + options.err_defs_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_WERROR_DEFS) + options.dos_defs_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_DOSERR_DEFS) + options.dos_desc_file = os.path.join(options.out_dir, WerrorGenerator.FNAME_DOSERR_DESC) + + # check options + _generate_files(options) -- cgit