mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
24905ba82d
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>
430 lines
17 KiB
Python
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)
|