#!/usr/bin/env bash read_header() { local key value i while read key value; do case "$key" in ---) break ;; HC:) header_comment="$value" ;; CC:) c_file_comment="$value" ;; OF:) output_file="$value" array_name=${value%command_list}cmds ;; SF:) source_files="$value" ;; AT:) array_type="$value" ;; IN:) for i in $value; do includes="$includes #include \"$i.h\"" done includes="$includes #include \"$output_file.h\"" ;; SN:) section_name="$value" ;; TM:) template_members="$value" esac done if test -z "$header_comment" -o -z "$c_file_comment" \ -o -z "$output_file"; then echo "header error" 1&>2 exit 1 fi } read_one_command() { local line name_txt="" desc_txt="" usage_txt="" help_txt="" perms_txt="" line_handler=0 template=0 template_name="" template_prototype="" mkdir -p man/man1 while read key value; do case "$key" in ---) break ;; N:) name_txt="$value" ;; T:) template_name="$value" template=1 ;; O:) template_prototype="$value" template=1 ;; P:) perms_txt="$value" ;; D:) desc_txt="$value" ;; L:) line_handler=1 ;; U:) usage_txt="$value" ;; H:) help_txt="${value}" while read line; do if test "$line" = "---"; then break; fi line=${line#H:} help_txt="$help_txt ${line# }" done break ;; esac done if test $template -eq 0; then if test -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \ -a -n "$help_txt"; then ret=1 return fi else if test -n "$template_name" -a -n "$template_prototype" \ -a -n "$name_txt " -a -n "$template_members" \ -a -n "$desc_txt" -a -n "$usage_txt" \ -a -n "$help_txt"; then ret=1 return fi fi if test -z "$name_txt" -a -z "$desc_txt" -a -z "$usage_txt" \ -a -z "$help_txt"; then ret=0 return fi ret=-1 #return echo "!ERROR!" echo "N: $name_txt" echo "D: $desc_txt" echo "S: $usage_txt" echo "P: $perms_txt" echo "H: $help_txt" echo "O: $template_prototype" } dump_man() { if test $template -eq 0; then echo ".SS \"$name_txt\"" echo "$desc_txt" echo echo "\\fBUsage: \\fP$usage_txt" else for member in $template_members; do local sed_cmd="sed -e s/@member@/$member/g" local t_name_txt=$(echo $name_txt | $sed_cmd) echo ".SS \"$t_name_txt\"" done echo "$desc_txt" | sed -e "s/@member@/{$(echo $template_members | sed -e 's/ / | /g')}/g" echo echo "\\fBUsage: \\fP" echo echo ".nf" for member in $template_members; do local sed_cmd="sed -e s/@member@/$member/g" local t_usage_txt=$(echo $usage_txt | $sed_cmd) printf "\t$t_usage_txt\n" done echo ".fi" fi echo echo "$help_txt" | sed -e 's/^ //' echo if test -n "$perms_txt"; then echo -n "\\fBpermissions:\\fP " if test "$perms_txt" = "0"; then echo "(none)" else echo "$perms_txt" fi fi echo } com_man() { echo "[$section_name]" echo while : ; do read_one_command if test $ret -lt 0; then exit 1 fi if test $ret -eq 0; then break fi dump_man done } dump_proto() { local source_file match="" echo '/**' echo " * $desc_txt" echo ' *' echo ' * \param fd The file descriptor to send output to.' if test $line_handler -eq 0; then echo ' * \param argc The number of arguments.' echo ' * \param argv The argument vector.' else echo ' * \param cmdline The full command line.' fi echo ' * ' echo " * Usage: $usage_txt" echo ' * ' echo "$help_txt" | sed -e 's/^/ * /g' echo ' */' if test -n "$prototype"; then echo "$prototype" echo return fi for source_file in $source_files; do match=$(grep "^\(__noreturn \)*int com_$name_txt(" $source_file | head -n 1 | sed -e 's/$/;/1') if test -n "$match"; then echo "$match" break fi done echo } dump_array_member() { echo '{' echo ".name = \"$name_txt\"," if test $line_handler -eq 0; then echo ".handler = com_$name_txt," else echo ".handler = NULL," echo ".line_handler = com_$name_txt," fi if test -n "$perms_txt"; then echo ".perms = $perms_txt," fi echo ".description = \"$desc_txt\"," echo ".usage = \"$usage_txt\"," echo ".help = " printf "%s\n" "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g' echo '},' } template_loop() { local t_name="$name_txt" local t_perms="$perms_txt" local t_desc="$desc_txt" local t_usage="$usage_txt" local t_help="$help_txt" local t_source_files="$source_files" local member for member in $template_members; do local sed_cmd="sed -e s/@member@/$member/g" #echo "sed_cmd: $sed_cmd" name_txt=$(echo $t_name | $sed_cmd) #name_txt="$tname" perms_txt=$(echo $t_perms | $sed_cmd) desc_txt=$(echo $t_desc | $sed_cmd) usage_txt=$(echo $t_usage | $sed_cmd) help_txt=$(printf "%s\n" "$t_help" | $sed_cmd) prototype=$(echo "$template_prototype" | $sed_cmd) $1 done } com_c_file() { echo "/** \file $output_file.c $c_file_comment */" echo "$includes" echo "struct $array_type $array_name[] = {" while : ; do read_one_command if test $ret -lt 0; then exit 1 fi if test $ret -eq 0; then break fi if test $template -eq 0; then dump_array_member continue fi template_loop dump_array_member done echo '{.name = NULL}};' } com_header() { echo "/** \file $output_file.h $header_comment */" echo echo "extern struct $array_type $array_name[];" while : ; do read_one_command if test $ret -lt 0; then exit 1 fi if test $ret -eq 0; then break fi if test $template -eq 0; then dump_proto continue fi template_loop dump_proto done } read_header arg="$1" shift case "$arg" in "c") com_c_file ;; "h") com_header ;; "man") com_man $* ;; esac