1258400Sdteske#!/bin/sh
2258400Sdteske#-
3258400Sdteske# Copyright (c) 2013 Devin Teske
4258400Sdteske# All rights reserved.
5258400Sdteske#
6258400Sdteske# Redistribution and use in source and binary forms, with or without
7258400Sdteske# modification, are permitted provided that the following conditions
8258400Sdteske# are met:
9258400Sdteske# 1. Redistributions of source code must retain the above copyright
10258400Sdteske#    notice, this list of conditions and the following disclaimer.
11258400Sdteske# 2. Redistributions in binary form must reproduce the above copyright
12258400Sdteske#    notice, this list of conditions and the following disclaimer in the
13258400Sdteske#    documentation and/or other materials provided with the distribution.
14258400Sdteske#
15258400Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16258400Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17258400Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18258400Sdteske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19258400Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20258400Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21258400Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22258400Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23258400Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24258400Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25258400Sdteske# SUCH DAMAGE.
26258400Sdteske#
27258400Sdteske# $FreeBSD$
28258400Sdteske#
29258400Sdteske############################################################ INCLUDES
30258400Sdteske
31258400Sdteske# Prevent common.subr from auto initializing debugging (this is not an inter-
32258401Sdteske# active utility that requires debugging; also `-d' has been repurposed).
33258400Sdteske#
34258400SdteskeDEBUG_SELF_INITIALIZE=NO
35258400Sdteske
36258400SdteskeBSDCFG_SHARE="/usr/share/bsdconfig"
37258400Sdteske. $BSDCFG_SHARE/common.subr || exit 1
38258400Sdteskef_dprintf "%s: loading includes..." "$0"
39258400Sdteske
40258400SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="includes"
41258400Sdteskef_include_lang $BSDCFG_LIBE/include/messages.subr
42258400Sdteskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
43258400Sdteske
44259054Sdteskef_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
45259054Sdteske	pgm="${ipgm:-$pgm}"
46258400Sdteske
47258400Sdteske############################################################ GLOBALS
48258400Sdteske
49258400Sdteske#
50258400Sdteske# Options
51258400Sdteske#
52258400SdteskeUSE_COLOR=1
53258401SdteskeSHOW_DESC=
54258400SdteskeSHOW_FUNCS=
55258400SdteskeFUNC_PATTERN=
56258400Sdteske
57258400Sdteske############################################################ FUNCTIONS
58258400Sdteske
59258400Sdteske# show_functions $file
60258400Sdteske#
61258400Sdteske# Show the functions in the given include file.
62258400Sdteske#
63258400Sdteskeshow_include()
64258400Sdteske{
65258400Sdteske	local file="${1#./}"
66258400Sdteske
67258400Sdteske	local pattern="${FUNC_PATTERN:-.*}"
68258401Sdteske	output=$( awk \
69258401Sdteske		-v use_color=${USE_COLOR:-0} \
70258401Sdteske		-v re="$pattern" \
71258401Sdteske		-v show_desc=${SHOW_DESC:-0} '
72273068Sdteske        function _asorti(src, dest)
73258785Sdteske        {
74273067Sdteske		k = nitems = 0;
75273067Sdteske
76258785Sdteske		# Copy src indices to dest and calculate array length
77273067Sdteske		for (i in src) dest[++nitems] = i
78258785Sdteske
79258785Sdteske		# Sort the array of indices (dest) using insertion sort method
80258785Sdteske		for (i = 1; i <= nitems; k = i++)
81258785Sdteske		{
82258785Sdteske			idx = dest[i]
83258785Sdteske			while ((k > 0) && (dest[k] > idx))
84258785Sdteske			{
85258785Sdteske				dest[k+1] = dest[k]
86258785Sdteske				k--
87258785Sdteske			}
88258785Sdteske			dest[k+1] = idx
89258785Sdteske		}
90258785Sdteske
91258785Sdteske		return nitems
92258785Sdteske        }
93258400Sdteske	/^$/,/^#/ {
94258400Sdteske		if ($0 ~ /^# f_/) {
95258400Sdteske			if (!match($2, re)) next
96258785Sdteske			fn = $2
97258400Sdteske			if (use_color)
98258785Sdteske				syntax[fn] = sprintf("+%s[1;31m%s[0m%s\n",
99258400Sdteske				       substr($0, 2, RSTART),
100258400Sdteske				       substr($0, 2 + RSTART, RLENGTH),
101258785Sdteske				       substr($0, 2 + RSTART + RLENGTH))
102258400Sdteske			else
103258785Sdteske				syntax[fn] = "+" substr($0, 2) "\n"
104258401Sdteske			if (show_desc)
105258401Sdteske				print_more = 1
106258401Sdteske			else
107258401Sdteske				print_more = substr($0, length($0)) == "\\"
108258400Sdteske		}
109258401Sdteske		if (show_desc && print_more) {
110258400Sdteske			getline
111258401Sdteske			while ($0 ~ /^#/) {
112258785Sdteske				syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
113258401Sdteske				getline
114258401Sdteske			}
115258401Sdteske			print_more = 0
116258401Sdteske		} else while (print_more) {
117258401Sdteske			getline
118258785Sdteske			syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
119258400Sdteske			print_more = substr($0, length($0)) == "\\"
120258400Sdteske		}
121258785Sdteske	}
122258785Sdteske	END {
123273068Sdteske		n = _asorti(syntax, sorted_indices)
124258785Sdteske		for (i = 1; i <= n; i++)
125258785Sdteske			printf "%s", syntax[sorted_indices[i]]
126258400Sdteske	}' "$file" )
127258400Sdteske	if [ "$output" ]; then
128258400Sdteske		if [ ! "$SHOW_FUNCS" ]; then
129258400Sdteske			echo "$file"
130258400Sdteske			return $SUCCESS
131258400Sdteske		fi
132258400Sdteske		if [ "$FUNC_PATTERN" ]; then
133258401Sdteske			printf ">>> $msg_functions_in_matching\n" \
134258400Sdteske			       "$file" "$FUNC_PATTERN"
135258400Sdteske		else
136258401Sdteske			printf ">>> $msg_functions_in\n" "$file"
137258400Sdteske		fi
138258400Sdteske		echo "$output"
139258400Sdteske		echo # blank line to simplify awk(1)-based reparse
140258400Sdteske	fi
141258400Sdteske}
142258400Sdteske
143258400Sdteske############################################################ MAIN
144258400Sdteske
145258400Sdteske# Incorporate rc-file if it exists
146258400Sdteske[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
147258400Sdteske
148258400Sdteske# Are we in a terminal?
149258400Sdteske[ -t 1 ] || USE_COLOR=
150258400Sdteske
151258400Sdteske#
152258400Sdteske# Process command-line arguments
153258400Sdteske#
154258401Sdteskewhile getopts adfF:hn flag; do
155258400Sdteske	case "$flag" in
156258400Sdteske	a) USE_COLOR=1 ;;
157258406Sdteske	d) SHOW_DESC=1 SHOW_FUNCS=1 ;;
158258400Sdteske	f) SHOW_FUNCS=1 ;;
159258400Sdteske	F) FUNC_PATTERN="$OPTARG" ;;
160258400Sdteske	n) USE_COLOR= ;;
161258400Sdteske	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
162258400Sdteske	esac
163258400Sdteskedone
164258400Sdteskeshift $(( $OPTIND - 1 ))
165258400Sdteske
166258400Sdteske# cd(1) to `share' dir so relative paths work for find and positional args
167258439Sdteskecd $BSDCFG_SHARE || f_die # Pedantic
168258400Sdteske
169258400Sdteske#
170258400Sdteske# If given an argument, operate on it specifically (implied `-f') and exit
171258400Sdteske#
172258400Sdteske[ $# -gt 0 ] && SHOW_FUNCS=1
173258400Sdteskefor include in "$@"; do
174258400Sdteske	# See if they've just omitted the `*.subr' suffix
175258400Sdteske	[ -f "$include.subr" -a ! -f "$include" ] && include="$include.subr"
176258400Sdteske	if [ ! -f "$include" ]; then
177258590Sdteske		printf "$msg_no_such_file_or_directory\n" "$0" "$include"
178258439Sdteske		exit $FAILURE
179258400Sdteske	elif [ ! -r "$include" ]; then
180258590Sdteske		printf "$msg_permission_denied\n" "$0" "$include"
181258439Sdteske		exit $FAILURE
182258400Sdteske	fi
183258400Sdteske	show_include "$include" || f_die
184258400Sdteskedone
185258400Sdteske
186258400Sdteske# Exit if we processed some include arguments
187258400Sdteske[ $# -gt 0 ] && exit $SUCCESS
188258400Sdteske
189258400Sdteske#
190258400Sdteske# Operate an all known include files
191258400Sdteske# NB: If we get this far, we had no include arguments
192258400Sdteske#
193258400Sdteskefind -s . -type f -and -iname '*.subr' | while read file; do
194258400Sdteske	if [ "$SHOW_FUNCS" -o "$FUNC_PATTERN" ]; then
195258400Sdteske		show_include "$file"
196258400Sdteske	else
197258400Sdteske		echo "${file#./}"
198258400Sdteske	fi
199258400Sdteskedone
200258400Sdteske
201258400Sdteskeexit $SUCCESS
202258400Sdteske
203258400Sdteske################################################################################
204258400Sdteske# END
205258400Sdteske################################################################################
206