blob: e8a86a96184cd9c475e2f9ef59f9c1b98f16b70c [file] [log] [blame] [raw]
#! /bin/bash
cd `dirname $0`
if [ $# -eq 2 ];
then
if [ `expr $2 : /` -eq 1 ];
then
output_dir=$2
else
output_dir=$1/$2
fi
else
output_dir=../objs
fi
list_file=data/action_list
types_file=data/action_types
reps_file=data/action_replacements
prefix_file=data/prefixes
header_file=data/header_files
optional_modules_file=data/modules_optional
headers_file=data/headers
module_dependencies_file=data/module_dependencies
conf_macros_file=data/conf_macros
conf_locs_file=data/conf_locs
conf_args_file=data/conf_args
autogen_notice=text/autogen
actions_dir=actions
srcs_dir=src
include_prefix=
file_prefix=ndk_
auto_file_name=config
auto_includes_name=includes
conf_merge_filename=conf_merge.h
conf_cmd_basic_filename=conf_cmd_basic.h
conf_cmd_extra_filename=conf_cmd_extra.h
spacer
sed_delete_empty_lines='t_NEL;d;:_NEL'
function trim_lines {
sed -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba' -e '}'
}
function strtoupper {
[ $# -eq 1 ] || return 1
local _str _cu _cl _x
_cu=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
_cl=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
_str=$1
for ((_x=0;_x<${#_cl[*]};_x++)); do
_str=${_str//${_cl[$_x]}/${_cu[$_x]}}
done
echo $_str
}
function sed_pad_right {
len=$1
spacer=$2
prefix=_PR$3
# returns a SED script that pads out (spaces) to the right to alignment $len
# this script should be used inside a call to sed
# NOTE : a spacer character $spacer should have already been written into the parsed string
echo "t${prefix}a;:${prefix}a;s/^[^$spacer]{$len}/&/;\
t${prefix}b;s/^[^$spacer]*/& /;t${prefix}a;:${prefix}b;s/$spacer/ /"
}
function sed_pad_left {
len=$1
spacer=$2
prefix=_PL$3
# echo "t${prefix}a;:${prefix}a;s/^[^$spacer]{$len}/& /;t${prefix}a" # NOT CORRECT?
}
function add_notice {
echo > $1
cat $autogen_notice | trim_lines >> $1
echo >> $1
echo >> $1
}
function add_non_generated_content {
file=src/$1.h
[ ! -f $file ] && return
echo "// Non-generated macros" >> $2
echo >> $2
cat $file | trim_lines >> $2
echo >> $2
echo >> $2
}
function add_action_macros {
list_file=$actions_dir/$1
[ ! -f $list_file ] && return
out=$2
# alignment settings
align1=20
align2=35
align3=62
base_shrink=12
define="#define "
# base macros
echo "// base action macro macros" >> $out
echo >> $out
cat $list_file | trim_lines | sed -r \
-e "s/^[ ]*([a-zA-Z0-9_]+)([ ]*)\(([a-zA-Z0-9_,]+)\)([ ]*)(.*)/$define%2%_\1_ac(\3,ac)\2\4 {\5;}/" \
-e "s/[ ]{$base_shrink}\{/\{/" \
-e 's/%A%/ac/g' \
>> $out
echo >> $out
echo >> $out
# generated macros
echo "// generated action macros" >> $out
echo >> $out
cat -s $list_file | while read list_line; do
[ "x`echo $list_line`" = 'x' ] && continue
cat $types_file | while read type_line; do
[ "x`echo $type_line`" = 'x' ] && continue
#ext=`echo $type_line | grep -E '^[a-zA-Z0-9_]+' | cut -d " " -f1`
ext=`echo $type_line | sed -r 's/^([a-zA-Z0-9_]+).*/\1/'`
params=`echo $type_line | sed -r 's/^[a-zA-Z0-9_]+[ ]*\((.*)\).*/\1/;ta;d;:a'`
act=`echo $type_line | sed -r 's/^[a-zA-Z0-9_]+[ ]*(\(.*\))?(.*)/\2/'`
[ "x$params" != "x" ] && params=",$params"
echo $list_line | sed -r \
-e "s/^([a-zA-Z0-9_]+)[ ]*\(([a-zA-Z0-9_,]+)\).*/%2%_\1_$ext(\2$params)$spacer%2%_\1_ac$spacer(\2,$act)/" \
-e 's/[ ]*,[ ]*/,/g' \
-e "`sed_pad_right $align2 $spacer 1`" \
-e "`sed_pad_right $align3 $spacer 2`" \
-e "s/.*/$define&/" \
>> $out
done
echo >> $out
done
}
function replace_prefixes {
temp=.temp
file=`cat $prefix_file`
prefix1=
prefix2=
for prefix in $file ; do
[ "x$prefix2" != "x" ] && echo "Too many prefixes in prefix file $prefix_file" && exit 1
[ "x$prefix1" != "x" ] && prefix2=$prefix && continue
prefix1=$prefix
done
sed -r "s/%1%/$prefix1/g;s/%2%/$prefix2/g" < $1 > $temp
mv -f $temp $1
}
function replace_other_strings {
temp=.temp
cat $reps_file | while read line; do
rep1=
rep2=
for rep in $line ; do
[ "x$rep2" != "x" ] && echo "Too many replacments in replacements file $reps_file" && exit 1
[ "x$rep1" != "x" ] && rep2=$rep && continue
rep1=$rep
done
sed -r "s/%$rep1%/$rep2/g" < $1 > $temp
mv -f $temp $1
done
}
function generate_header_file {
name=$1
out=$output_dir/$file_prefix$name.h
add_notice $out
add_non_generated_content $name $out
add_action_macros $name $out
replace_prefixes $out
replace_other_strings $out
}
function add_auto_include {
echo "#include <${file_prefix}$2>" >> $1
}
function add_include {
echo "#include <${include_prefix}${file_prefix}$2>" >> $1
}
function generate_non_optional_h_includes {
# TODO : split into auto-generated and non-auto-generated ones
echo "// non-optional includes" >> $1
echo >> $1
for mod in `cat $headers_file | sort`; do
add_auto_include $1 $mod.h
done
echo >> $1
echo >> $1
}
function generate_include_all_includes {
echo "// include all optional modules" >> $1
echo >> $1
echo "#ifdef NDK_ALL" >> $1
echo >> $1
modules=`cat $optional_modules_file | sed 's/*//g' | sort`
for mod in $modules; do
def="NDK_`strtoupper $mod`"
echo "#ifndef $def" >> $1
echo "#define $def 1" >> $1
echo "#endif" >> $1
done
echo >> $1
echo "#endif" >> $1
echo >> $1
echo >> $1
}
function generate_dependent_includes {
echo "// module dependencies" >> $1
echo >> $1
cat $module_dependencies_file | while read line; do
first=1
for mod in $line; do
def="NDK_`strtoupper $mod`"
if [ $first = 1 ] ; then
echo "#ifdef $def" >> $1
first=0
else
echo "#ifndef $def" >> $1
echo "#define $def 1" >> $1
echo "#endif" >> $1
fi
done
[ $first = 0 ] && echo "#endif" >> $1
done
echo >> $1
echo >> $1
}
function generate_optional_h_includes {
echo "// optional includes" >> $1
echo >> $1
for mod in $modules; do
def="NDK_`strtoupper $mod`"
echo "#if ($def)" >> $1
add_include $1 $mod.h
echo "#endif" >> $1
done
echo >> $1
echo >> $1
}
function generate_conf_merge_macros_file {
file=$conf_merge_filename
out_file=${file_prefix}$file
out=$output_dir/$out_file
add_notice $out
echo "// conf-merge-value macros" >> $out
echo >> $out
cat $srcs_dir/$file | trim_lines >> $out
echo >> $out
echo >> $out
echo "// conf-merge-prop macros" >> $out
echo >> $out
echo "#define ndk_conf_merge_prop(prop,default)\\" >> $out
echo " ndk_conf_merge_value\\" >> $out
echo " (conf->prop, prev->prop, default)" >> $out
echo >> $out
# loads macros, removes empty elements, sorts and translates to merge-prop macros
cat $conf_macros_file | sed -r 's/^[A-Z0-9_]+[ ]*[A-Z0-9_]+[ ]*([a-z0-9_]+).*$/\1/;ta;d;:a' \
| sort | sed -r \
's/(.*)/#define ndk_conf_merge_\1_prop(prop,default,...)\\\
ndk_conf_merge_\1_value\\\
(conf->prop, prev->prop, default,##__VA_ARGS__)\
/' \
>> $out
add_auto_include $1 $file
}
function generate_conf_cmd_basic_file {
temp=.rep
file=$conf_cmd_basic_filename
out_file=${file_prefix}$file
out=$output_dir/$out_file
align1=35
# initial text
add_notice $out
# add ndk bitmasks
echo "// conf cmd core values/bitmasks" >> $out
echo >> $out
cat $conf_args_file | sort | trim_lines | sed -r \
-e "s/^([A-Z0-9_]+)/${define}NDK_\1${spacer}NGX_\1/" \
-e $sed_delete_empty_lines \
-e "`sed_pad_right $align1 $spacer`" \
>> $out
echo >> $out
echo >> $out
# add additional bitmasks stored in file
echo "// conf cmd bitmasks" >> $out
echo >> $out
cat $srcs_dir/$conf_cmd_basic_filename | trim_lines >> $out
echo >> $out
echo >> $out
echo "// conf cmd basic macros" >> $out
echo >> $out
# build replacement string
echo -n "s/^([A-Z0-9_]+)$/" > $temp
cat $conf_locs_file | sed \
-r -e 's/^([A-Z0-9_]+) *([A-Z0-9_]+).*/#define NDK_\1_CONF_\\1\(name,func,off1,off2,post)\\\\\\\
{ngx_string (name),\\\\\\\
NGX_CONF_\\1|NDK_\1_CONF,\\\\\\\
func, off1, off2, post},\\\
\\/' -e $sed_delete_empty_lines \
>> $temp
echo -n "/;$sed_delete_empty_lines" >> $temp
# apply the replacement string to the
cat $conf_args_file | sort | trim_lines | sed -rf $temp >> $out
rm -f $temp
add_auto_include $1 $file
}
function generate_conf_cmd_extra_file {
temp=.rep
file=$conf_cmd_extra_filename
out=$output_dir/${file_prefix}$file
align1=35
# initial text
add_notice $out
echo "// conf command macros" >> $out
echo >> $out
# build replacement string
echo -n 's/^([A-Z0-9_]+)[ ]*([A-Z0-9_]+)[ ]*([a-z0-9_]+).*$/' > $temp
cat $conf_locs_file | sed \
-r -e 's/^([A-Z0-9_]+)[ ]*([A-Z0-9_]+)[ ]*([a-zA-Z0-9_]+)/#define NDK_\1_CONF_\\1(name,p,post\)\\\\\\\
NDK_\1_CONF_\\2\\\\\\\
(name,\\\\\\\
ndk_conf_set_\\3_slot,\\\\\\\
NGX_\2_CONF_OFFSET,\\\\\\\
offsetof (ndk_module_\3_conf_t, p),\\\\\\\
post)\\\
\\/' -e $sed_delete_empty_lines \
>> $temp
echo -n "/;$sed_delete_empty_lines" >> $temp
#echo -n ";`sed_pad_right 60 $spacer`" >> $temp
# apply the replacement string to the
cat $conf_macros_file | sort | trim_lines | sed -rf $temp -e "`sed_pad_right 60 $spacer`" >> $out
rm -f $temp
add_auto_include $1 $file
}
function generate_auto_generated_h_includes {
echo "// auto-generated headers" >> $1
echo >> $1
for name in `cat $header_file | sort` ; do
generate_header_file $name
add_auto_include $1 $name.h
done
generate_conf_merge_macros_file $1
generate_conf_cmd_basic_file $1
generate_conf_cmd_extra_file $1
echo >> $1
echo >> $1
}
function generate_optional_c_includes {
echo "// optional includes" >> $1
echo >> $1
modules=`cat $optional_modules_file | sed 's/*//g' | sort`
for mod in $modules; do
def="NDK_`strtoupper "$mod"`"
echo "#if ($def)" >> $1
add_include $1 $mod.c
echo "#endif" >> $1
done
echo >> $1
echo >> $1
}
function generate_commands {
echo "// module commands" >> $1
echo >> $1
echo "static ngx_command_t ndk_http_commands[] = {" >> $1
cat $optional_modules_file | sort | while read line; do
cmds=`echo "$line" | grep -E '\*'`
[ "x$cmds" = "x" ] && continue
mod=`echo "$line" | grep -E '^[a-zA-Z0-9_]+' | cut -d " " -f1`
up=`strtoupper $mod`
def="NDK_$up"
defcmd="NDK_${up}_CMDS"
echo "#if ($def)" >> $1
echo "#define $defcmd 1" >> $1
add_include $1 $mod.h
echo "#undef $defcmd" >> $1
echo "#endif" >> $1
done
echo -e " ngx_null_command\n};" >> $1
}
function generate_all_h_files {
out=$output_dir/${file_prefix}$auto_file_name.h
add_notice $out
generate_include_all_includes $out
generate_dependent_includes $out
out=$output_dir/${file_prefix}$auto_includes_name.h
generate_optional_h_includes $out
generate_non_optional_h_includes $out
generate_auto_generated_h_includes $out $list
}
function generate_all_c_files {
out=$output_dir/${file_prefix}$auto_file_name.c
add_notice $out
generate_optional_c_includes $out
generate_commands $out
}
function generate_all_files {
mkdir -p $output_dir
rm -f $output_dir/*
generate_all_h_files
generate_all_c_files
}
generate_all_files