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 " )
2014-01-24 07:45:31 +04:00
parser . add_option ( " --mode " , type = " choice " , metavar = " <FUNCTIONS|S3PROTO|LIBPROTO|PARAMDEFS> " ,
choices = [ " FUNCTIONS " , " S3PROTO " , " LIBPROTO " , " PARAMDEFS " ] , default = " FUNCTIONS " )
2014-01-15 07:49:50 +04:00
parser . add_option ( " --scope " , metavar = " <GLOBAL|LOCAL> " ,
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 ' )
except IOError , 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 " )
if synonym == " 1 " or removed == " 1 " or generated == " 0 " :
continue
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 ( )
yield { ' name ' : name ,
' type ' : param_type ,
' context ' : context ,
' function ' : func ,
' constant ' : ( constant == ' 1 ' ) ,
' parm ' : ( parm == ' 1 ' ) }
# 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 " }
2014-01-15 07:49:50 +04:00
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
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
f . write ( output_string + " ( " + parameter [ ' function ' ] + " , " + parameter [ ' function ' ] + ' ) \n ' )
finally :
f . close ( )
2014-01-14 08:53:49 +04:00
2014-01-15 07:49:50 +04:00
mapping = { ' boolean ' : ' bool ' , ' string ' : ' char * ' , ' integer ' : ' int ' , ' char ' : ' char ' ,
' list ' : ' const char ** ' , ' enum ' : ' int ' , ' boolean-auto ' : ' int ' }
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
output_string = " "
if parameter [ ' constant ' ] :
output_string + = ' const '
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 ' 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
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 :
raise Exception ( parameter [ ' name ' ] + " has an invalid context " + parameter [ ' context ' ] )
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
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 " )
file_out . write ( " \t char * dnsdomain; \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 " )
for parameter in iterate_all ( path_in ) :
# filter out parameteric options
if ' : ' in parameter [ ' name ' ] :
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_ %s S \n " % scope )
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 )