2014-01-14 08:53:49 +04:00
# 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 errno
import os
import re
import subprocess
import xml . etree . ElementTree as ET
import sys
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 " )
2015-06-18 08:37:24 +03:00
parser . add_option ( " --mode " , type = " choice " , metavar = " <FUNCTIONS|S3PROTO|LIBPROTO|PARAMDEFS|PARAMTABLE> " ,
2018-07-30 09:16:12 +03:00
choices = [ " FUNCTIONS " , " S3PROTO " , " LIBPROTO " , " PARAMDEFS " , " PARAMTABLE " ] , default = " FUNCTIONS " )
2014-01-15 07:49:50 +04:00
parser . add_option ( " --scope " , metavar = " <GLOBAL|LOCAL> " ,
2018-07-30 09:19:21 +03:00
choices = [ " GLOBAL " , " LOCAL " ] , default = " GLOBAL " )
2014-01-14 08:53:49 +04:00
( 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 ' )
2018-02-14 00:36:22 +03:00
except IOError as e :
2014-01-14 08:53:49 +04:00
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 " )
2015-06-18 08:37:24 +03:00
handler = parameter . attrib . get ( " handler " )
enumlist = parameter . attrib . get ( " enumlist " )
deprecated = parameter . attrib . get ( " deprecated " )
synonyms = parameter . findall ( ' synonym ' )
2015-04-28 17:47:39 +03:00
if removed == " 1 " :
2014-01-14 08:53:49 +04:00
continue
2015-04-28 17:47:39 +03:00
2014-01-14 08:53:49 +04:00
constant = parameter . attrib . get ( " constant " )
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 ( )
2015-06-18 08:37:24 +03:00
if enumlist is None :
enumlist = " NULL "
if handler is None :
handler = " NULL "
2014-01-14 08:53:49 +04:00
yield { ' name ' : name ,
' type ' : param_type ,
' context ' : context ,
' function ' : func ,
' constant ' : ( constant == ' 1 ' ) ,
2015-04-28 17:47:39 +03:00
' parm ' : ( parm == ' 1 ' ) ,
' synonym ' : synonym ,
2015-06-18 08:37:24 +03:00
' generated ' : generated ,
' enumlist ' : enumlist ,
' handler ' : handler ,
' deprecated ' : deprecated ,
2018-07-30 09:17:14 +03:00
' synonyms ' : synonyms }
2014-01-14 08:53:49 +04:00
# map doc attributes to a section of the generated function
context_dict = { " G " : " _GLOBAL " , " S " : " _LOCAL " }
2015-07-23 19:00:41 +03:00
param_type_dict = {
" boolean " : " _BOOL " ,
" list " : " _LIST " ,
" string " : " _STRING " ,
" integer " : " _INTEGER " ,
" enum " : " _INTEGER " ,
" char " : " _CHAR " ,
" boolean-auto " : " _INTEGER " ,
2015-07-23 19:01:40 +03:00
" cmdlist " : " _LIST " ,
" bytes " : " _INTEGER " ,
" octal " : " _INTEGER " ,
" ustring " : " _STRING " ,
2015-07-23 19:00:41 +03:00
}
2014-01-14 08:53:49 +04:00
2014-01-15 07:49:50 +04:00
def generate_functions ( path_in , path_out ) :
f = open ( path_out , ' w ' )
try :
2018-07-30 09:13:57 +03:00
f . write ( ' /* This file was automatically generated by generate_param.py. DO NOT EDIT */ \n \n ' )
for parameter in iterate_all ( options . filename ) :
2014-01-15 07:49:50 +04:00
# filter out parameteric options
if ' : ' in parameter [ ' name ' ] :
continue
2015-04-28 17:47:39 +03:00
if parameter [ ' synonym ' ] == " 1 " :
continue
if parameter [ ' generated ' ] == " 0 " :
continue
2014-01-15 07:49:50 +04:00
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 [ ' constant ' ] :
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
2018-07-30 09:18:03 +03:00
f . write ( output_string + " ( " + parameter [ ' function ' ] + " , " + parameter [ ' function ' ] + ' ) \n ' )
2014-01-15 07:49:50 +04:00
finally :
f . close ( )
2014-01-14 08:53:49 +04:00
2015-07-23 19:00:41 +03:00
mapping = {
' boolean ' : ' bool ' ,
' string ' : ' char * ' ,
' integer ' : ' int ' ,
' char ' : ' char ' ,
' list ' : ' const char ** ' ,
' enum ' : ' int ' ,
' boolean-auto ' : ' int ' ,
2015-07-23 19:01:40 +03:00
' cmdlist ' : ' const char ** ' ,
' bytes ' : ' int ' ,
' octal ' : ' int ' ,
' ustring ' : ' char * ' ,
2015-07-23 19:00:41 +03:00
}
2014-01-15 07:49:50 +04:00
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
2015-04-28 17:47:39 +03:00
if parameter [ ' synonym ' ] == " 1 " :
continue
if parameter [ ' generated ' ] == " 0 " :
continue
2014-01-15 07:49:50 +04:00
output_string = " "
if parameter [ ' constant ' ] :
output_string + = ' const '
param_type = mapping . get ( parameter [ ' type ' ] )
if param_type is None :
2018-07-30 09:13:57 +03:00
raise Exception ( parameter [ ' name ' ] + " has an invalid context " + parameter [ ' context ' ] )
2014-01-15 07:49:50 +04:00
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 ' and not parameter [ ' constant ' ] :
if parameter [ ' context ' ] == ' G ' :
output_string + = ' (TALLOC_CTX *ctx); \n '
elif parameter [ ' context ' ] == ' S ' :
output_string + = ' (TALLOC_CTX *ctx, %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
2015-04-28 17:47:39 +03:00
if parameter [ ' synonym ' ] == " 1 " :
continue
if parameter [ ' generated ' ] == " 0 " :
continue
2014-01-15 07:49:50 +04:00
output_string = " "
2014-01-17 01:30:37 +04:00
if parameter [ ' constant ' ] :
2014-01-15 07:49:50 +04:00
output_string + = ' const '
param_type = mapping . get ( parameter [ ' type ' ] )
if param_type is None :
2018-07-30 09:13:57 +03:00
raise Exception ( parameter [ ' name ' ] + " has an invalid context " + parameter [ ' context ' ] )
2014-01-15 07:49:50 +04:00
output_string + = param_type
output_string + = " lpcfg_ %s " % parameter [ ' function ' ]
2014-01-17 01:30:37 +04:00
if parameter [ ' type ' ] == ' string ' and not parameter [ ' constant ' ] :
if parameter [ ' context ' ] == ' G ' :
output_string + = ' (struct loadparm_context *, 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 param type " + parameter [ ' type ' ] )
2014-01-15 07:49:50 +04:00
else :
2014-01-17 01:30:37 +04:00
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 ' ] )
2014-01-15 07:49:50 +04:00
2018-07-30 09:13:57 +03:00
2014-01-15 07:49:50 +04:00
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 ( " \t TALLOC_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 ( " \t bool autoloaded; \n " )
2018-07-30 09:13:57 +03:00
2014-01-15 07:49:50 +04:00
for parameter in iterate_all ( path_in ) :
# filter out parameteric options
if ' : ' in parameter [ ' name ' ] :
continue
2015-04-28 17:47:39 +03:00
if parameter [ ' synonym ' ] == " 1 " :
continue
2014-01-15 07:49:50 +04:00
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 :
2018-07-30 09:13:57 +03:00
raise Exception ( parameter [ ' name ' ] + " has an invalid context " + parameter [ ' context ' ] )
2014-01-15 07:49:50 +04:00
output_string + = param_type
output_string + = " %s ; \n " % parameter [ ' function ' ]
file_out . write ( output_string )
file_out . write ( " LOADPARM_EXTRA_ %s S \n " % scope )
file_out . write ( " }; \n " )
file_out . write ( " \n #endif /* %s */ \n \n " % header )
finally :
file_out . close ( )
2015-06-18 08:37:24 +03:00
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 { NULL, P_BOOL, P_NONE, 0, NULL, NULL, 0} \n " ) ;
file_out . write ( " }; \n " )
file_out . write ( " \n #endif /* %s */ \n \n " % header )
finally :
file_out . close ( )
2014-01-15 07:49:50 +04:00
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 )
2015-06-18 08:37:24 +03:00
elif options . mode == ' PARAMTABLE ' :
make_param_table ( options . filename , options . output )