1#!/bin/sh
2#-
3# Copyright (c) 2013 Devin Teske
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28#
29############################################################ INCLUDES
30
31# Prevent common.subr from auto initializing debugging (this is not an inter-
32# active utility that requires debugging; also `-d' has been repurposed).
33#
34DEBUG_SELF_INITIALIZE=NO
35
36BSDCFG_SHARE="/usr/share/bsdconfig"
37. $BSDCFG_SHARE/common.subr || exit 1
38f_dprintf "%s: loading includes..." "$0"
39
40BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="includes"
41f_include_lang $BSDCFG_LIBE/include/messages.subr
42f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
43
44f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
45	pgm="${ipgm:-$pgm}"
46
47############################################################ GLOBALS
48
49#
50# Options
51#
52USE_COLOR=1
53SHOW_DESC=
54SHOW_FUNCS=
55FUNC_PATTERN=
56
57############################################################ FUNCTIONS
58
59# show_functions $file
60#
61# Show the functions in the given include file.
62#
63show_include()
64{
65	local file="${1#./}"
66
67	local pattern="${FUNC_PATTERN:-.*}"
68	output=$( awk \
69		-v use_color=${USE_COLOR:-0} \
70		-v re="$pattern" \
71		-v show_desc=${SHOW_DESC:-0} '
72        function _asorti(src, dest)
73        {
74		k = nitems = 0;
75
76		# Copy src indices to dest and calculate array length
77		for (i in src) dest[++nitems] = i
78
79		# Sort the array of indices (dest) using insertion sort method
80		for (i = 1; i <= nitems; k = i++)
81		{
82			idx = dest[i]
83			while ((k > 0) && (dest[k] > idx))
84			{
85				dest[k+1] = dest[k]
86				k--
87			}
88			dest[k+1] = idx
89		}
90
91		return nitems
92        }
93	/^$/,/^#/ {
94		if ($0 ~ /^# f_/) {
95			if (!match($2, re)) next
96			fn = $2
97			if (use_color)
98				syntax[fn] = sprintf("+%s%s%s\n",
99				       substr($0, 2, RSTART),
100				       substr($0, 2 + RSTART, RLENGTH),
101				       substr($0, 2 + RSTART + RLENGTH))
102			else
103				syntax[fn] = "+" substr($0, 2) "\n"
104			if (show_desc)
105				print_more = 1
106			else
107				print_more = substr($0, length($0)) == "\\"
108		}
109		if (show_desc && print_more) {
110			getline
111			while ($0 ~ /^#/) {
112				syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
113				getline
114			}
115			print_more = 0
116		} else while (print_more) {
117			getline
118			syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
119			print_more = substr($0, length($0)) == "\\"
120		}
121	}
122	END {
123		n = _asorti(syntax, sorted_indices)
124		for (i = 1; i <= n; i++)
125			printf "%s", syntax[sorted_indices[i]]
126	}' "$file" )
127	if [ "$output" ]; then
128		if [ ! "$SHOW_FUNCS" ]; then
129			echo "$file"
130			return $SUCCESS
131		fi
132		if [ "$FUNC_PATTERN" ]; then
133			printf ">>> $msg_functions_in_matching\n" \
134			       "$file" "$FUNC_PATTERN"
135		else
136			printf ">>> $msg_functions_in\n" "$file"
137		fi
138		echo "$output"
139		echo # blank line to simplify awk(1)-based reparse
140	fi
141}
142
143############################################################ MAIN
144
145# Incorporate rc-file if it exists
146[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
147
148# Are we in a terminal?
149[ -t 1 ] || USE_COLOR=
150
151#
152# Process command-line arguments
153#
154while getopts adfF:hn flag; do
155	case "$flag" in
156	a) USE_COLOR=1 ;;
157	d) SHOW_DESC=1 SHOW_FUNCS=1 ;;
158	f) SHOW_FUNCS=1 ;;
159	F) FUNC_PATTERN="$OPTARG" ;;
160	n) USE_COLOR= ;;
161	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
162	esac
163done
164shift $(( $OPTIND - 1 ))
165
166# cd(1) to `share' dir so relative paths work for find and positional args
167cd $BSDCFG_SHARE || f_die # Pedantic
168
169#
170# If given an argument, operate on it specifically (implied `-f') and exit
171#
172[ $# -gt 0 ] && SHOW_FUNCS=1
173for include in "$@"; do
174	# See if they've just omitted the `*.subr' suffix
175	[ -f "$include.subr" -a ! -f "$include" ] && include="$include.subr"
176	if [ ! -f "$include" ]; then
177		printf "$msg_no_such_file_or_directory\n" "$0" "$include"
178		exit $FAILURE
179	elif [ ! -r "$include" ]; then
180		printf "$msg_permission_denied\n" "$0" "$include"
181		exit $FAILURE
182	fi
183	show_include "$include" || f_die
184done
185
186# Exit if we processed some include arguments
187[ $# -gt 0 ] && exit $SUCCESS
188
189#
190# Operate an all known include files
191# NB: If we get this far, we had no include arguments
192#
193find -s . -type f -and -iname '*.subr' | while read file; do
194	if [ "$SHOW_FUNCS" -o "$FUNC_PATTERN" ]; then
195		show_include "$file"
196	else
197		echo "${file#./}"
198	fi
199done
200
201exit $SUCCESS
202
203################################################################################
204# END
205################################################################################
206