1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/script/generate_param.py
Ralph Boehme 24905ba82d docs-xml: remove explicit "constant"
The constant mark applied to types "string" and "ustring". The previous patches
in this patchset already markes all string options as either constant or
substituted, but it's still possible to add options or change existing ones to
be neither constant nor substituted.

In order to enforce strings to be either constant or substitued, remove the
explicit constant marker. Instead, any option that is not marked as substituted
is implicitly made constant.

This patch doesn't change behaviour and all generated files are the same before
and after this change.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2019-11-27 10:25:37 +00:00

430 lines
17 KiB
Python

# Unix SMB/CIFS implementation.
# Copyright (C) 2014 Catalyst.Net Ltd
#
# Auto generate param_functions.c
#
# ** NOTE! The following LGPL license applies to the ldb
# ** library. This does NOT imply that all of Samba is released
# ** under the LGPL
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
#
import os
import xml.etree.ElementTree as ET
import optparse
# parse command line arguments
parser = optparse.OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="input file", metavar="FILE")
parser.add_option("-o", "--output", dest="output",
help='output file', metavar="FILE")
parser.add_option("--mode", type="choice", metavar="<FUNCTIONS|S3PROTO|LIBPROTO|PARAMDEFS|PARAMTABLE>",
choices=["FUNCTIONS", "S3PROTO", "LIBPROTO", "PARAMDEFS", "PARAMTABLE"], default="FUNCTIONS")
parser.add_option("--scope", metavar="<GLOBAL|LOCAL>",
choices=["GLOBAL", "LOCAL"], default="GLOBAL")
(options, args) = parser.parse_args()
if options.filename is None:
parser.error("No input file specified")
if options.output is None:
parser.error("No output file specified")
def iterate_all(path):
"""Iterate and yield all the parameters.
:param path: path to parameters xml file
"""
try:
p = open(path, 'r')
except IOError as e:
raise Exception("Error opening parameters file")
out = p.read()
# parse the parameters xml file
root = ET.fromstring(out)
for parameter in root:
name = parameter.attrib.get("name")
param_type = parameter.attrib.get("type")
context = parameter.attrib.get("context")
func = parameter.attrib.get("function")
synonym = parameter.attrib.get("synonym")
removed = parameter.attrib.get("removed")
generated = parameter.attrib.get("generated_function")
handler = parameter.attrib.get("handler")
enumlist = parameter.attrib.get("enumlist")
deprecated = parameter.attrib.get("deprecated")
synonyms = parameter.findall('synonym')
if removed == "1":
continue
constant = parameter.attrib.get("constant")
substitution = parameter.attrib.get("substitution")
parm = parameter.attrib.get("parm")
if name is None or param_type is None or context is None:
raise Exception("Error parsing parameter: " + name)
if func is None:
func = name.replace(" ", "_").lower()
if enumlist is None:
enumlist = "NULL"
if handler is None:
handler = "NULL"
yield {'name': name,
'type': param_type,
'context': context,
'function': func,
'constant': (constant == '1'),
'substitution': (substitution == '1'),
'parm': (parm == '1'),
'synonym' : synonym,
'generated' : generated,
'enumlist' : enumlist,
'handler' : handler,
'deprecated' : deprecated,
'synonyms' : synonyms }
# map doc attributes to a section of the generated function
context_dict = {"G": "_GLOBAL", "S": "_LOCAL"}
param_type_dict = {
"boolean" : "_BOOL",
"list" : "_LIST",
"string" : "_STRING",
"integer" : "_INTEGER",
"enum" : "_INTEGER",
"char" : "_CHAR",
"boolean-auto" : "_INTEGER",
"cmdlist" : "_LIST",
"bytes" : "_INTEGER",
"octal" : "_INTEGER",
"ustring" : "_STRING",
}
def generate_functions(path_in, path_out):
f = open(path_out, 'w')
try:
f.write('/* This file was automatically generated by generate_param.py. DO NOT EDIT */\n\n')
for parameter in iterate_all(options.filename):
# filter out parameteric options
if ':' in parameter['name']:
continue
if parameter['synonym'] == "1":
continue
if parameter['generated'] == "0":
continue
output_string = "FN"
temp = context_dict.get(parameter['context'])
if temp is None:
raise Exception(parameter['name'] + " has an invalid context " + parameter['context'])
output_string += temp
if parameter['type'] == "string" or parameter['type'] == "ustring":
if parameter['substitution']:
output_string += "_SUBSTITUTED"
else:
output_string += "_CONST"
if parameter['parm']:
output_string += "_PARM"
temp = param_type_dict.get(parameter['type'])
if temp is None:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
output_string += temp
f.write(output_string + "(" + parameter['function'] + ", " + parameter['function'] + ')\n')
finally:
f.close()
mapping = {
'boolean' : 'bool ',
'string' : 'char *',
'integer' : 'int ',
'char' : 'char ',
'list' : 'const char **',
'enum' : 'int ',
'boolean-auto' : 'int ',
'cmdlist' : 'const char **',
'bytes' : 'int ',
'octal' : 'int ',
'ustring' : 'char *',
}
def make_s3_param_proto(path_in, path_out):
file_out = open(path_out, 'w')
try:
file_out.write('/* This file was automatically generated by generate_param.py. DO NOT EDIT */\n\n')
header = get_header(path_out)
file_out.write("#ifndef %s\n" % header)
file_out.write("#define %s\n\n" % header)
for parameter in iterate_all(path_in):
# filter out parameteric options
if ':' in parameter['name']:
continue
if parameter['synonym'] == "1":
continue
if parameter['generated'] == "0":
continue
output_string = ""
param_type = mapping.get(parameter['type'])
if param_type is None:
raise Exception(parameter['name'] + " has an invalid context " + parameter['context'])
output_string += param_type
output_string += "lp_%s" % parameter['function']
param = None
if parameter['parm']:
param = "const struct share_params *p"
else:
param = "int"
if parameter['type'] == 'string' or parameter['type'] == 'ustring':
if parameter['substitution']:
if parameter['context'] == 'G':
output_string += '(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub);\n'
elif parameter['context'] == 'S':
output_string += '(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub, %s);\n' % param
else:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
else:
if parameter['context'] == 'G':
output_string = 'const ' + output_string + '(void);\n'
elif parameter['context'] == 'S':
output_string = 'const ' + output_string + '(%s);\n' % param
else:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
else:
if parameter['context'] == 'G':
output_string += '(void);\n'
elif parameter['context'] == 'S':
output_string += '(%s);\n' % param
else:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
file_out.write(output_string)
file_out.write("\n#endif /* %s */\n\n" % header)
finally:
file_out.close()
def make_lib_proto(path_in, path_out):
file_out = open(path_out, 'w')
try:
file_out.write('/* This file was automatically generated by generate_param.py. DO NOT EDIT */\n\n')
for parameter in iterate_all(path_in):
# filter out parameteric options
if ':' in parameter['name']:
continue
if parameter['synonym'] == "1":
continue
if parameter['generated'] == "0":
continue
output_string = ""
param_type = mapping.get(parameter['type'])
if param_type is None:
raise Exception(parameter['name'] + " has an invalid context " + parameter['context'])
output_string += param_type
output_string += "lpcfg_%s" % parameter['function']
if parameter['type'] == 'string' or parameter['type'] == 'ustring':
if parameter['substitution']:
if parameter['context'] == 'G':
output_string += '(struct loadparm_context *, const struct loadparm_substitution *lp_sub, TALLOC_CTX *ctx);\n'
elif parameter['context'] == 'S':
output_string += '(struct loadparm_service *, struct loadparm_service *, TALLOC_CTX *ctx);\n'
else:
raise Exception(parameter['name'] + " has an invalid context " + parameter['context'])
else:
if parameter['context'] == 'G':
output_string = 'const ' + output_string + '(struct loadparm_context *);\n'
elif parameter['context'] == 'S':
output_string = 'const ' + output_string + '(struct loadparm_service *, struct loadparm_service *);\n'
else:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
else:
if parameter['context'] == 'G':
output_string += '(struct loadparm_context *);\n'
elif parameter['context'] == 'S':
output_string += '(struct loadparm_service *, struct loadparm_service *);\n'
else:
raise Exception(parameter['name'] + " has an invalid param type " + parameter['type'])
file_out.write(output_string)
finally:
file_out.close()
def get_header(path):
header = os.path.basename(path).upper()
header = header.replace(".", "_").replace("\\", "_").replace("-", "_")
return "__%s__" % header
def make_param_defs(path_in, path_out, scope):
file_out = open(path_out, 'w')
try:
file_out.write('/* This file was automatically generated by generate_param.py. DO NOT EDIT */\n\n')
header = get_header(path_out)
file_out.write("#ifndef %s\n" % header)
file_out.write("#define %s\n\n" % header)
if scope == "GLOBAL":
file_out.write("/**\n")
file_out.write(" * This structure describes global (ie., server-wide) parameters.\n")
file_out.write(" */\n")
file_out.write("struct loadparm_global \n")
file_out.write("{\n")
file_out.write("\tTALLOC_CTX *ctx; /* Context for talloced members */\n")
elif scope == "LOCAL":
file_out.write("/**\n")
file_out.write(" * This structure describes a single service.\n")
file_out.write(" */\n")
file_out.write("struct loadparm_service \n")
file_out.write("{\n")
file_out.write("\tbool autoloaded;\n")
for parameter in iterate_all(path_in):
# filter out parameteric options
if ':' in parameter['name']:
continue
if parameter['synonym'] == "1":
continue
if (scope == "GLOBAL" and parameter['context'] != "G" or
scope == "LOCAL" and parameter['context'] != "S"):
continue
output_string = "\t"
param_type = mapping.get(parameter['type'])
if param_type is None:
raise Exception(parameter['name'] + " has an invalid context " + parameter['context'])
output_string += param_type
output_string += " %s;\n" % parameter['function']
file_out.write(output_string)
file_out.write("LOADPARM_EXTRA_%sS\n" % scope)
file_out.write("};\n")
file_out.write("\n#endif /* %s */\n\n" % header)
finally:
file_out.close()
type_dict = {
"boolean" : "P_BOOL",
"boolean-rev" : "P_BOOLREV",
"boolean-auto" : "P_ENUM",
"list" : "P_LIST",
"string" : "P_STRING",
"integer" : "P_INTEGER",
"enum" : "P_ENUM",
"char" : "P_CHAR",
"cmdlist" : "P_CMDLIST",
"bytes" : "P_BYTES",
"octal" : "P_OCTAL",
"ustring" : "P_USTRING",
}
def make_param_table(path_in, path_out):
file_out = open(path_out, 'w')
try:
file_out.write('/* This file was automatically generated by generate_param.py. DO NOT EDIT */\n\n')
header = get_header(path_out)
file_out.write("#ifndef %s\n" % header)
file_out.write("#define %s\n\n" % header)
file_out.write("struct parm_struct parm_table[] = {\n")
for parameter in iterate_all(path_in):
# filter out parameteric options
if ':' in parameter['name']:
continue
if parameter['context'] == 'G':
p_class = "P_GLOBAL"
else:
p_class = "P_LOCAL"
p_type = type_dict.get(parameter['type'])
if parameter['context'] == 'G':
temp = "GLOBAL"
else:
temp = "LOCAL"
offset = "%s_VAR(%s)" % (temp, parameter['function'])
enumlist = parameter['enumlist']
handler = parameter['handler']
synonym = parameter['synonym']
deprecated = parameter['deprecated']
flags_list = []
if synonym == "1":
flags_list.append("FLAG_SYNONYM")
if deprecated == "1":
flags_list.append("FLAG_DEPRECATED")
flags = "|".join(flags_list)
synonyms = parameter['synonyms']
file_out.write("\t{\n")
file_out.write("\t\t.label\t\t= \"%s\",\n" % parameter['name'])
file_out.write("\t\t.type\t\t= %s,\n" % p_type)
file_out.write("\t\t.p_class\t= %s,\n" % p_class)
file_out.write("\t\t.offset\t\t= %s,\n" % offset)
file_out.write("\t\t.special\t= %s,\n" % handler)
file_out.write("\t\t.enum_list\t= %s,\n" % enumlist)
if flags != "":
file_out.write("\t\t.flags\t\t= %s,\n" % flags)
file_out.write("\t},\n")
if synonyms is not None:
# for synonyms, we only list the synonym flag:
flags = "FLAG_SYNONYM"
for syn in synonyms:
file_out.write("\t{\n")
file_out.write("\t\t.label\t\t= \"%s\",\n" % syn.text)
file_out.write("\t\t.type\t\t= %s,\n" % p_type)
file_out.write("\t\t.p_class\t= %s,\n" % p_class)
file_out.write("\t\t.offset\t\t= %s,\n" % offset)
file_out.write("\t\t.special\t= %s,\n" % handler)
file_out.write("\t\t.enum_list\t= %s,\n" % enumlist)
if flags != "":
file_out.write("\t\t.flags\t\t= %s,\n" % flags)
file_out.write("\t},\n")
file_out.write("\n\t{ .label = NULL }\n")
file_out.write("};\n")
file_out.write("\n#endif /* %s */\n\n" % header)
finally:
file_out.close()
if options.mode == 'FUNCTIONS':
generate_functions(options.filename, options.output)
elif options.mode == 'S3PROTO':
make_s3_param_proto(options.filename, options.output)
elif options.mode == 'LIBPROTO':
make_lib_proto(options.filename, options.output)
elif options.mode == 'PARAMDEFS':
make_param_defs(options.filename, options.output, options.scope)
elif options.mode == 'PARAMTABLE':
make_param_table(options.filename, options.output)