1252995Sdteske#!/bin/sh
2252995Sdteske#-
3252995Sdteske# Copyright (c) 2012-2013 Devin Teske
4252995Sdteske# All rights reserved.
5252995Sdteske#
6252995Sdteske# Redistribution and use in source and binary forms, with or without
7252995Sdteske# modification, are permitted provided that the following conditions
8252995Sdteske# are met:
9252995Sdteske# 1. Redistributions of source code must retain the above copyright
10252995Sdteske#    notice, this list of conditions and the following disclaimer.
11252995Sdteske# 2. Redistributions in binary form must reproduce the above copyright
12252995Sdteske#    notice, this list of conditions and the following disclaimer in the
13252995Sdteske#    documentation and/or other materials provided with the distribution.
14252995Sdteske#
15252995Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16252995Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17252995Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18252995Sdteske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19252995Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20252995Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21252995Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22252995Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23252995Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24252995Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25252995Sdteske# SUCH DAMAGE.
26252995Sdteske#
27252995Sdteske# $FreeBSD$
28252995Sdteske#
29252995Sdteske############################################################ INCLUDES
30252995Sdteske
31252995Sdteske# Prevent common.subr from auto initializing debugging (this is not an inter-
32266292Sdteske# active utility so does not require debugging; also `-d' has been repurposed).
33252995Sdteske#
34252995SdteskeDEBUG_SELF_INITIALIZE=NO
35252995Sdteske
36252995SdteskeBSDCFG_SHARE="/usr/share/bsdconfig"
37252995Sdteske. $BSDCFG_SHARE/common.subr || exit 1
38252995Sdteskef_dprintf "%s: loading includes..." "$0"
39252995Sdteske
40252995SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="dot"
41252995Sdteskef_include_lang $BSDCFG_LIBE/include/messages.subr
42252995Sdteskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
43252995Sdteske
44263791Sdteskef_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
45263791Sdteske	pgm="${ipgm:-$pgm}"
46252995Sdteske
47252995Sdteske############################################################ CONFIGURATION
48252995Sdteske
49252995Sdteske#
50252995Sdteske# Location of bsdconfig(8)
51252995Sdteske#
52252995SdteskeBSDCONFIG=/usr/sbin/bsdconfig
53252995Sdteske
54252995Sdteske############################################################ GLOBALS
55252995Sdteske
56252995Sdteske#
57252995Sdteske# Options
58252995Sdteske#
59252995SdteskeSHOW_GRAPH_LABEL_DATE=1
60252995SdteskeSHOW_INCLUDES=1
61252995SdteskeSHOW_CMDLINE=1
62252995Sdteske
63252995Sdteske############################################################ FUNCTIONS
64252995Sdteske
65252995Sdteske# begin_nodelist $shape $color $fillcolor $style
66252995Sdteske#
67252995Sdteske# Create a new multi-node list rendering nodes in a specific style described by
68252995Sdteske# the arguments passed.
69252995Sdteske#
70252995Sdteskebegin_nodelist()
71252995Sdteske{
72252995Sdteske	local shape="$1" color="$2" fillcolor="$3" style="$4"
73252995Sdteske
74252995Sdteske	printf "\tnode [\n"
75252995Sdteske	[ "$shape" ] &&
76252995Sdteske		printf '\t\tshape = "%s",\n' "$shape"
77252995Sdteske	[ "$color" ] &&
78252995Sdteske		printf '\t\tcolor = "%s",\n' "$color"
79252995Sdteske	[ "$fillcolor" ] &&
80252995Sdteske		printf '\t\tfillcolor = "%s",\n' "$fillcolor"
81252995Sdteske	[ "$style" ] &&
82252995Sdteske		printf '\t\tstyle = "%s",\n' "$style"
83252995Sdteske	printf "\t] {\n"
84252995Sdteske}
85252995Sdteske
86252995Sdteske# print_node $node [$attributes ...]
87252995Sdteske#
88252995Sdteske# Print a node within a multi-node list.
89252995Sdteske#
90252995Sdteskeprint_node()
91252995Sdteske{
92252995Sdteske	local node="$1"
93252995Sdteske
94252995Sdteske	shift 1 # node
95252995Sdteske
96252995Sdteske	case "$node" in
97252995Sdteske	edge) printf '\t\t%s' "$node" ;;
98252995Sdteske	   *) printf '\t\t"%s"' "$node" ;;
99252995Sdteske	esac
100252995Sdteske
101252995Sdteske	if [ $# -gt 0 ]; then
102252995Sdteske		echo -n ' ['
103252995Sdteske		while [ $# -gt 0 ]; do
104252995Sdteske			printf " %s" "$1"
105252995Sdteske			shift 1
106252995Sdteske			[ $# -gt 0 ] && echo -n ","
107252995Sdteske		done
108252995Sdteske		echo -n " ]"
109252995Sdteske	fi
110252995Sdteske
111252995Sdteske	echo ";"
112252995Sdteske}
113252995Sdteske
114252995Sdteske# print_node2 $node $node [$attributes ...]
115252995Sdteske#
116252995Sdteske# Print a directed node-node connection within a multi-node list.
117252995Sdteske#
118252995Sdteskeprint_node2()
119252995Sdteske{
120252995Sdteske	local node1="$1" node2="$2"
121252995Sdteske
122252995Sdteske	shift 2 # node1 node2
123252995Sdteske
124252995Sdteske	printf '\t\t"%s" -> "%s"' "$node1" "$node2"
125252995Sdteske
126252995Sdteske	if [ $# -gt 0 ]; then
127252995Sdteske		echo -n ' ['
128252995Sdteske		while [ $# -gt 0 ]; do
129252995Sdteske			printf " %s" "$1"
130252995Sdteske			shift 1
131252995Sdteske			[ $# -gt 0 ] && echo -n ","
132252995Sdteske		done
133252995Sdteske		echo -n " ]"
134252995Sdteske	fi
135252995Sdteske
136252995Sdteske	echo ";"
137252995Sdteske}
138252995Sdteske
139252995Sdteske# end_nodelist
140252995Sdteske#
141252995Sdteske# Close a multi-node list.
142252995Sdteske#
143252995Sdteskeend_nodelist()
144252995Sdteske{
145252995Sdteske	printf "\t};\n"
146252995Sdteske}
147252995Sdteske
148252995Sdteske############################################################ MAIN
149252995Sdteske
150252995Sdteske# Incorporate rc-file if it exists
151252995Sdteske[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
152252995Sdteske
153252995Sdteske#
154252995Sdteske# Process command-line arguments
155252995Sdteske#
156252995Sdteskewhile getopts cdhi flag; do
157252995Sdteske	case "$flag" in
158252995Sdteske	i) SHOW_INCLUDES= ;;
159252995Sdteske	d) SHOW_GRAPH_LABEL_DATE= ;;
160252995Sdteske	c) SHOW_CMDLINE= ;;
161252995Sdteske	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
162252995Sdteske	esac
163252995Sdteskedone
164252995Sdteskeshift $(( $OPTIND - 1 ))
165252995Sdteske
166263791Sdteskecd $BSDCFG_LIBE || f_die # Pedantic
167252995Sdteske
168252995Sdteske#
169252995Sdteske# Get a list of menu programs
170252995Sdteske#
171252995Sdteskemenu_program_list=
172252995Sdteskefor file in [0-9][0-9][0-9].*/INDEX; do
173252995Sdteske	menu_program_list="$menu_program_list $(
174252995Sdteske		tail -r "$file" | awk -v item="${file%%/*}" '
175252995Sdteske			/^[[:space:]]*menu_program="/ {
176252995Sdteske				sub(/^.*="/, "")
177252995Sdteske				sub(/"$/, "")
178252995Sdteske				if ( ! $0 ) next
179252995Sdteske				if ( $0 !~ "^/" ) sub(/^/, item "/")
180252995Sdteske				print; exit
181252995Sdteske			}'
182252995Sdteske	)"
183252995Sdteskedone
184252995Sdteske
185252995Sdteske#
186252995Sdteske# Get a list of submenu programs
187252995Sdteske#
188252995Sdteskesubmenu_program_list=
189252995Sdteskefor menu_program in $menu_program_list; do
190252995Sdteske	case "$menu_program" in
191252995Sdteske	[0-9][0-9][0-9].*/*) : fall-through ;;
192252995Sdteske	*) continue # No sub-menus we can process
193252995Sdteske	esac
194252995Sdteske
195252995Sdteske	submenu_program_list="$submenu_program_list $(
196252995Sdteske		awk -v menu_program="$menu_program" \
197252995Sdteske		    -v item="${menu_program%%/*}" \
198252995Sdteske		'
199252995Sdteske			/^menu_selection="/ {
200252995Sdteske				sub(/.*\|/, "")
201252995Sdteske				sub(/"$/, "")
202252995Sdteske				if ( ! $0 ) next
203252995Sdteske				if ( $0 !~ "^/" )
204252995Sdteske					sub(/^/, item "/")
205252995Sdteske				if ( $0 == menu_program ) next
206252995Sdteske				print
207252995Sdteske			}
208252995Sdteske		' "${menu_program%%/*}/INDEX"
209252995Sdteske	)"
210252995Sdteskedone
211252995Sdteske
212252995Sdteske#
213252995Sdteske# Get a list of command-line programs
214252995Sdteske#
215252995Sdteskecmd_program_list=
216252995Sdteskefor file in */INDEX; do
217252995Sdteske	cmd_program_list="$cmd_program_list $(
218252995Sdteske		awk -v item="${file%%/*}" '
219252995Sdteske			/^menu_selection="/ {
220252995Sdteske				sub(/.*\|/, "")
221252995Sdteske				sub(/"$/, "")
222252995Sdteske
223252995Sdteske				if ( ! $0 ) next
224252995Sdteske
225252995Sdteske				if ( $0 !~ "^/" )
226252995Sdteske					sub(/^/, item "/")
227252995Sdteske
228252995Sdteske				print
229252995Sdteske			}
230252995Sdteske		' $file
231252995Sdteske	)"
232252995Sdteskedone
233252995Sdteske
234252995Sdteske#
235252995Sdteske# [Optionally] Calculate list of include files
236252995Sdteske#
237252995Sdteskeif [ "$SHOW_INCLUDES" ]; then
238252995Sdteske	print_includes_awk='
239252995Sdteske		BEGIN { regex = "^f_include \\$BSDCFG_SHARE/" }
240252995Sdteske		( $0 ~ regex ) { sub(regex, ""); print }
241252995Sdteske	' # END-QUOTE
242252995Sdteske
243252995Sdteske	#
244252995Sdteske	# Build list of files in which to search for includes
245252995Sdteske	#
246252995Sdteske	file_list=$(
247252995Sdteske		for file in \
248252995Sdteske			$BSDCONFIG \
249252995Sdteske			$menu_program_list \
250252995Sdteske			$submenu_program_list \
251252995Sdteske			$cmd_program_list \
252252995Sdteske		; do
253252995Sdteske			[ -e "$file" ] && echo $file
254252995Sdteske		done | sort -u
255252995Sdteske	)
256252995Sdteske
257252995Sdteske	#
258252995Sdteske	# Build list of includes used by the above files
259252995Sdteske	#
260252995Sdteske	include_file_list=
261252995Sdteske	for file in $file_list; do
262252995Sdteske		include_file_list="$include_file_list $(
263252995Sdteske			awk "$print_includes_awk" $file
264252995Sdteske		)"
265252995Sdteske	done
266252995Sdteske
267252995Sdteske	#
268252995Sdteske	# Sort the list of includes and remove duplicate entries
269252995Sdteske	#
270252995Sdteske	include_file_list=$(
271252995Sdteske		for include_file in $include_file_list; do
272252995Sdteske			echo "$include_file"
273252995Sdteske		done | sort -u
274252995Sdteske	)
275252995Sdteske
276252995Sdteske	#
277252995Sdteske	# Search previously-discovered include files for further includes
278252995Sdteske	#
279252995Sdteske	before="$include_file_list"
280252995Sdteske	while :; do
281252995Sdteske		for file in $include_file_list; do
282252995Sdteske			include_file_list="$include_file_list $(
283252995Sdteske				awk "$print_includes_awk" $BSDCFG_SHARE/$file
284252995Sdteske			)"
285252995Sdteske		done
286252995Sdteske
287252995Sdteske		#
288252995Sdteske		# Sort list of includes and remove duplicate entries [again]
289252995Sdteske		#
290252995Sdteske		include_file_list=$(
291252995Sdteske			for include_file in $include_file_list; do
292252995Sdteske				echo "$include_file"
293252995Sdteske			done | sort -u
294252995Sdteske		)
295252995Sdteske
296252995Sdteske		[ "$include_file_list" = "$before" ] && break
297252995Sdteske		before="$include_file_list"
298252995Sdteske	done
299252995Sdteskefi
300252995Sdteske
301252995Sdteske#
302252995Sdteske# Add script.subr to includes if it exists
303252995Sdteske#
304252995Sdteske[ -f $BSDCFG_SHARE/script.subr ] &&
305252995Sdteske	include_file_list="$include_file_list script.subr"
306252995Sdteske
307252995Sdteske#
308252995Sdteske# Start the directional-graph (digraph) output
309252995Sdteske#
310252995Sdteskeprintf 'strict digraph "" { // Empty name to prevent SVG Auto-Tooltip\n'
311252995Sdteskelabel_format="$msg_graph_label_with_command"
312252995Sdteske[ "$SHOW_GRAPH_LABEL_DATE" ] &&
313252995Sdteske	label_format="$msg_graph_label_with_command_and_date"
314252995Sdteskelang="${LANG:-$LC_ALL}"
315252995Sdteskeprintf "\n\tlabel = \"$label_format\"\n" \
316252995Sdteske       "${lang:+LANG=${lang%%[$IFS]*} }bsdconfig $pgm${ARGV:+ $ARGV}" \
317252995Sdteske       "$( date +"%c %Z" )"
318252995Sdteske
319252995Sdteske#
320252995Sdteske# Print graph-specific properties
321252995Sdteske#
322252995Sdteskeprintf '\n\t/*\n\t * Graph setup and orientation\n\t */\n'
323252995Sdteskeprintf '\tlabelloc = top;\t\t// display above label at top of graph\n'
324252995Sdteskeprintf '\trankdir = LR;\t\t// create ranks left-to-right\n'
325252995Sdteskeprintf '\torientation = portrait;\t// default\n'
326252995Sdteskeprintf '\tratio = fill;\t\t// approximate aspect ratio\n'
327252995Sdteskeprintf '\tcenter = 1;\t\t// center drawing on page\n'
328252995Sdteske
329252995Sdteske#
330252995Sdteske# Perform edge-concentration when displaying a lot of information
331252995Sdteske#
332252995Sdteske# NOTE: This is disabled because dot(1) version 2.28.0 (current) and older have
333252995Sdteske#       a bug that causes a crash when rankdir = LR and concentrate = true
334252995Sdteske#
335252995Sdteske# NOTE: Do not re-enable until said bug is fixed in some future revision.
336252995Sdteske#
337252995Sdteske#[ "$SHOW_INCLUDES" -a "$SHOW_CMDLINE" ] &&
338252995Sdteske#	printf '\tconcentrate = true;\t// enable edge concentrators\n'
339252995Sdteske
340252995Sdteske#
341252995Sdteske# Print font details for graph/cluster label(s)
342252995Sdteske#
343252995Sdteskeprintf '\n\t/*\n\t * Font details for graph/cluster label(s)\n\t */\n'
344252995Sdteskeprintf '\tfontname = "Times-Italic";\n'
345252995Sdteskeprintf '\tfontsize = 14;\n'
346252995Sdteske
347252995Sdteske#
348252995Sdteske# Print default node attributes
349252995Sdteske#
350252995Sdteskeprintf '\n\t/*\n\t * Default node attributes\n\t */\n'
351252995Sdteskeprintf '\tnode [\n'
352252995Sdteskeprintf '\t\tfontname = "Times-Roman",\n'
353252995Sdteskeprintf '\t\tfontsize = 12,\n'
354252995Sdteskeprintf '\t\twidth = 2.5, // arbitrary minimum width for all nodes\n'
355252995Sdteskeprintf '\t\tfixedsize,   // turn minimum width into exact width\n'
356252995Sdteskeprintf '\t];\n'
357252995Sdteske
358252995Sdteske#
359252995Sdteske# Print top-level item(s)
360252995Sdteske#
361252995Sdteskeprintf '\n\t/*\n\t * bsdconfig(8)\n\t */\n'
362252995Sdteskeshape=circle color=black fillcolor=yellow style=filled
363252995Sdteskebegin_nodelist "$shape" "$color" "$fillcolor" "$style"
364252995Sdteskeprint_node "bsdconfig" "fontname = \"Times-Bold\"" "fontsize = 16"
365252995Sdteskeend_nodelist
366252995Sdteske
367252995Sdteske#
368252995Sdteske# Print menus
369252995Sdteske#
370252995Sdteskeprintf '\n\t/*\n\t * Menu items\n\t */\n'
371252995Sdteskeshape=box color=black fillcolor=lightblue style=filled
372252995Sdteskebegin_nodelist "$shape" "$color" "$fillcolor" "$style"
373252995Sdteskefor menu_program in $menu_program_list; do
374252995Sdteske	print_node "$menu_program" "label = \"${menu_program#*/}\""
375252995Sdteskedone
376252995Sdteskeend_nodelist
377252995Sdteske
378252995Sdteske#
379252995Sdteske# Print sub-menus
380252995Sdteske#
381252995Sdteskeprintf '\n\t/*\n\t * Sub-menu items\n\t */\n'
382252995Sdteskeshape=box color=black fillcolor=lightblue style=filled
383252995Sdteskebegin_nodelist "$shape" "$color" "$fillcolor" "$style"
384252995Sdteskefor submenu_program in $submenu_program_list; do
385252995Sdteske	print_node "$submenu_program" "label = \"${submenu_program#*/}\""
386252995Sdteskedone
387252995Sdteskeend_nodelist
388252995Sdteske
389252995Sdteske#
390252995Sdteske# Print menu relationships
391252995Sdteske#
392252995Sdteskeprintf '\n\t/*\n\t * Menu item relationships\n\t */\n'
393252995Sdteskeshape=box color=black fillcolor=lightblue style=filled edge_color=blue
394252995Sdteskebegin_nodelist "$shape" "$color" "$fillcolor" "$style"
395252995Sdteskeprint_node edge "penwidth = 5.0" "style = bold" "color = $edge_color"
396252995Sdteskefor menu_program in $menu_program_list; do
397252995Sdteske	print_node2 "bsdconfig" "$menu_program"
398252995Sdteskedone
399252995Sdteskeend_nodelist
400252995Sdteske
401252995Sdteske#
402252995Sdteske# Print sub-menu relationships
403252995Sdteske#
404252995Sdteskeprintf '\n\t/*\n\t * Sub-menu item relationships\n\t */\n'
405252995Sdteskeshape=box color=black fillcolor=lightblue style=filled edge_color=blue
406252995Sdteskebegin_nodelist "$shape" "$color" "$fillcolor" "$style"
407252995Sdteske# Lock sub-menu headport to the West (unless `-c' was passed)
408252995Sdteske[ "$SHOW_CMDLINE" -o ! "$SHOW_INCLUDES" ] && print_node edge "headport = w"
409252995Sdteskeprint_node edge "style = bold" "color = $edge_color"
410252995Sdteskefor submenu_program in $submenu_program_list; do
411252995Sdteske	for menu_program in $menu_program_list; do
412252995Sdteske		case "$menu_program" in
413252995Sdteske		[0-9][0-9][0-9].*/*) : fall-through ;;
414252995Sdteske		*) continue # Not a menu item
415252995Sdteske		esac
416252995Sdteske
417252995Sdteske		# Continue if program directories do not match
418252995Sdteske		[ "${menu_program%%/*}" = "${submenu_program%%/*}" ] ||
419252995Sdteske			continue
420252995Sdteske
421252995Sdteske		print_node2 "$menu_program" "$submenu_program"
422252995Sdteske		break
423252995Sdteske	done
424252995Sdteskedone
425252995Sdteskeend_nodelist
426252995Sdteske
427252995Sdteske#
428252995Sdteske# [Optionally] Print include files
429252995Sdteske#
430252995Sdteskeif [ "$SHOW_INCLUDES" ]; then
431252995Sdteske	printf '\n\t/*\n\t * Include files\n\t */\n'
432252995Sdteske	shape=oval color=black fillcolor=white style=filled
433252995Sdteske	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
434252995Sdteske	printf '\t\tconstraint = false;\n'
435252995Sdteske	for include_file in $include_file_list; do
436252995Sdteske		print_node "$include_file" \
437252995Sdteske		           "label = \"${include_file##*/}\""
438252995Sdteske	done
439252995Sdteske	end_nodelist
440252995Sdteskefi
441252995Sdteske
442252995Sdteske#
443252995Sdteske# [Optionally] Print f_include() usage/relationships
444252995Sdteske#
445252995Sdteskeif [ "$SHOW_INCLUDES" ]; then
446252995Sdteske	printf '\n\t/*\n\t * Include usage\n\t */\n'
447252995Sdteske	shape=oval color=black fillcolor=white style=filled edge_color=grey
448252995Sdteske	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
449252995Sdteske	print_node edge "style = dashed" "color = $edge_color"
450252995Sdteske	#print_node edge "label = \"\\T\"" "fontsize = 9"
451252995Sdteske		# NOTE: Edge labels are buggy on large graphs
452252995Sdteske	file_list=$(
453252995Sdteske		for file in \
454252995Sdteske			$BSDCONFIG \
455252995Sdteske			$menu_program_list \
456252995Sdteske			$submenu_program_list \
457252995Sdteske			$cmd_program_list \
458252995Sdteske			$include_file_list \
459252995Sdteske		; do
460252995Sdteske			[ -f "$BSDCFG_SHARE/$file" ] &&
461252995Sdteske				echo $BSDCFG_SHARE/$file
462252995Sdteske			[ -e "$file" ] && echo $file
463252995Sdteske		done | sort -u
464252995Sdteske	)
465252995Sdteske	for file in $file_list; do
466252995Sdteske		# Skip binary files and text files that don't use f_include()
467252995Sdteske		grep -qlI f_include $file || continue
468252995Sdteske
469252995Sdteske		awk \
470252995Sdteske			-v file="${file#$BSDCFG_SHARE/}" \
471252995Sdteske			-v bsdconfig="$BSDCONFIG" \
472252995Sdteske		'
473252995Sdteske			BEGIN { regex = "^f_include \\$BSDCFG_SHARE/" }
474252995Sdteske			( $0 ~ regex ) {
475252995Sdteske				sub(regex, "")
476252995Sdteske				if ( file == bsdconfig ) sub(".*/", "", file)
477252995Sdteske				printf "\t\t\"%s\" -> \"%s\";\n", $0, file
478252995Sdteske			}
479252995Sdteske		' $file
480252995Sdteske	done | sort
481252995Sdteske	end_nodelist
482252995Sdteskefi
483252995Sdteske
484252995Sdteske#
485252995Sdteske# Print command-line shortcuts
486252995Sdteske#
487252995Sdteskeif [ "$SHOW_CMDLINE" ]; then
488252995Sdteske	printf '\n\t/*\n\t * Command-line shortcuts\n\t */\n'
489252995Sdteske	shape=parallelogram color=black fillcolor=lightseagreen style=filled
490252995Sdteske	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
491252995Sdteske	for file in */INDEX; do
492252995Sdteske		awk -v item="${file%%/*}" '
493252995Sdteske			/^menu_selection="/ {
494252995Sdteske				sub(/^.*="/, "")
495252995Sdteske				sub(/\|.*/, "")
496252995Sdteske				printf "\t\t\"bsdconfig %s\"", $0
497252995Sdteske				printf " [ label = \"%s\" ];\n", $0
498252995Sdteske			}
499252995Sdteske		' $file
500252995Sdteske	done
501252995Sdteske	end_nodelist
502252995Sdteskefi
503252995Sdteske
504252995Sdteske#
505252995Sdteske# Print command-line shortcut relationships
506252995Sdteske#
507252995Sdteskeif [ "$SHOW_CMDLINE" ]; then
508252995Sdteske	printf '\n\t/*\n\t * Command-line shortcut relationships\n\t */\n'
509252995Sdteske	shape=box color=black fillcolor=lightseagreen style=filled
510252995Sdteske	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
511252995Sdteske	print_node edge "headport = w" "weight = 100.0"
512252995Sdteske	print_node edge "style = bold" "color = $fillcolor"
513252995Sdteske	for file in */INDEX; do
514252995Sdteske		awk -v item="${file%%/*}" \
515252995Sdteske		    -v node_fillcolor="$node_fillcolor" \
516252995Sdteske		    -v edge_color="$edge_color" \
517252995Sdteske		'
518252995Sdteske			/^menu_selection="/ {
519252995Sdteske				sub(/^.*="/, "")
520252995Sdteske				sub(/"$/, "")
521252995Sdteske
522252995Sdteske				if ( ! $0 ) next
523252995Sdteske
524252995Sdteske				split($0, menusel, "|")
525252995Sdteske				if ( menusel[2] !~ "^/" )
526252995Sdteske					sub(/^/, item "/", menusel[2])
527252995Sdteske
528252995Sdteske				printf "\t\t\"bsdconfig %s\" -> \"%s\";\n",
529252995Sdteske				       menusel[1], menusel[2]
530252995Sdteske			}
531252995Sdteske		' $file
532252995Sdteske	done
533252995Sdteske	end_nodelist
534252995Sdteskefi
535252995Sdteske
536252995Sdteske#
537252995Sdteske# Print clusters
538252995Sdteske#
539252995Sdteskebgcolor_bsdconfig="lightyellow"
540252995Sdteskebgcolor_includes="gray98"
541252995Sdteskebgcolor_menuitem="aliceblue"
542252995Sdteskebgcolor_shortcuts="honeydew"
543252995Sdteskeprintf '\n\t/*\n\t * Clusters\n\t */\n'
544252995Sdteskeprintf '\tsubgraph "cluster_bsdconfig" {\n'
545252995Sdteskeprintf '\t\tbgcolor = "%s";\n' "$bgcolor_bsdconfig"
546252995Sdteskeprintf '\t\tlabel = "bsdconfig(8)";\n'
547252995Sdteskeprintf '\t\ttooltip = "bsdconfig(8)";\n'
548252995Sdteskeprint_node "bsdconfig"
549252995Sdteskeif [ "$SHOW_INCLUDES" ]; then
550252995Sdteske	printf '\t\tsubgraph "cluster_includes" {\n'
551252995Sdteske	printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes"
552252995Sdteske	printf '\t\t\tlabel = "%s";\n' "$msg_includes"
553252995Sdteske
554252995Sdteske	for include_file in $include_file_list; do
555252995Sdteske		echo $include_file
556252995Sdteske	done | awk -v bgcolor="$bgcolor_bsdconfig" '
557252995Sdteske	BEGIN { created = 0 }
558252995Sdteske	function end_subgraph() { printf "\t\t\t};\n" }
559252995Sdteske	( $0 !~ "/" ) {
560252995Sdteske		if ( ! created )
561252995Sdteske		{
562252995Sdteske			printf "\t\t\tsubgraph \"%s\" {\n",
563252995Sdteske			       "cluster_bsdconfig_includes"
564252995Sdteske			printf "\t\t\t\tbgcolor = \"%s\";\n", bgcolor
565252995Sdteske			printf "\t\t\t\tlabel = \"bsdconfig\";\n"
566252995Sdteske			created++
567252995Sdteske		}
568252995Sdteske		printf "\t\t\t\t\"%s\";\n", $1
569252995Sdteske	}
570252995Sdteske	END { created && end_subgraph() }'
571252995Sdteske
572252995Sdteske	for include_file in $include_file_list; do
573252995Sdteske		echo $include_file
574252995Sdteske	done | awk '
575252995Sdteske	BEGIN { created = 0 }
576252995Sdteske	function end_subgraph() { printf "\t\t\t};\n" }
577252995Sdteske	( $0 ~ "/" ) {
578252995Sdteske		include_dir_tmp = $1
579252995Sdteske		sub("/[^/]*$", "", include_dir_tmp)
580252995Sdteske		gsub(/[^[:alnum:]_]/, "_", include_dir_tmp)
581252995Sdteske
582252995Sdteske		if ( created && include_dir != include_dir_tmp )
583252995Sdteske		{
584252995Sdteske			end_subgraph()
585252995Sdteske			created = 0
586252995Sdteske		}
587252995Sdteske
588252995Sdteske		if ( ! created )
589252995Sdteske		{
590252995Sdteske			include_dir = include_dir_tmp
591252995Sdteske			printf "\t\t\tsubgraph \"cluster_%s_includes\" {\n",
592252995Sdteske			       include_dir
593252995Sdteske			printf "\t\t\t\tbgcolor = \"white\";\n"
594252995Sdteske			printf "\t\t\t\tlabel = \"%s\";\n", include_dir
595252995Sdteske			created++
596252995Sdteske		}
597252995Sdteske
598252995Sdteske		printf "\t\t\t\t\"%s\";\n", $1
599252995Sdteske	}
600252995Sdteske	END { created && end_subgraph() }'
601252995Sdteske
602252995Sdteske	printf '\t\t};\n'
603252995Sdteskefi
604252995Sdteskeend_nodelist
605252995Sdteskefor INDEX in */INDEX; do
606252995Sdteske	menu_title=
607252995Sdteske	menu_help=
608252995Sdteske	f_include_lang "$INDEX"
609252995Sdteske
610252995Sdteske	item="${INDEX%%/*}"
611252995Sdteske	printf '\tsubgraph "cluster_%s" {\n' "$item"
612252995Sdteske
613252995Sdteske	case "$item" in
614252995Sdteske	[0-9][0-9][0-9].*) bgcolor="$bgcolor_menuitem" ;;
615252995Sdteske	*) bgcolor="$bgcolor_shortcuts"
616252995Sdteske	esac
617252995Sdteske	printf '\t\tbgcolor = "%s";\n' "$bgcolor"
618252995Sdteske	if [ "$menu_title" ]; then
619252995Sdteske		printf '\t\tlabel = "%s\\n\\"%s\\"";\n' "$item" "$menu_title"
620252995Sdteske	else
621252995Sdteske		printf '\t\tlabel = "%s";\n' "$item"
622252995Sdteske	fi
623252995Sdteske	printf '\t\ttooltip = "%s";\n' "${menu_help:-$item}"
624252995Sdteske
625252995Sdteske	program_list=$(
626252995Sdteske		for program in \
627252995Sdteske			$menu_program_list \
628252995Sdteske			$submenu_program_list \
629252995Sdteske			$cmd_program_list \
630252995Sdteske		; do
631252995Sdteske			echo "$program"
632252995Sdteske		done | sort -u
633252995Sdteske	)
634252995Sdteske	for program in $program_list; do
635252995Sdteske		case "$program" in "$item"/*)
636252995Sdteske			print_node "$program" "label = \"${program#*/}\""
637252995Sdteske		esac
638252995Sdteske	done
639252995Sdteske
640252995Sdteske	if [ "$SHOW_INCLUDES" ]; then
641252995Sdteske		item_include_list=
642252995Sdteske		[ -d "$item/include" ] &&
643252995Sdteske			item_include_list=$( find "$item/include" -type f )
644252995Sdteske		item_include_list=$(
645252995Sdteske			for item_include in $item_include_list; do
646252995Sdteske				for include_file in $include_file_list; do
647252995Sdteske					[ "$item_include" = "$include_file" ] ||
648252995Sdteske						continue
649252995Sdteske					echo "$item_include"; break
650252995Sdteske				done
651252995Sdteske			done
652252995Sdteske		)
653252995Sdteske		if [ "$item_include_list" ]; then
654252995Sdteske			printf '\t\tsubgraph "cluster_%s_includes" {\n' "$item"
655252995Sdteske			printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes"
656252995Sdteske			printf '\t\t\tlabel = "%s";\n' "$msg_includes"
657252995Sdteske		fi
658252995Sdteske		for item_include in $item_include_list; do
659252995Sdteske			printf '\t\t\t"%s";\n' "$item_include"
660252995Sdteske		done
661252995Sdteske		[ "$item_include_list" ] && printf '\t\t};\n'
662252995Sdteske	fi
663252995Sdteske
664252995Sdteske	if [ "$SHOW_CMDLINE" ]; then
665252995Sdteske		printf '\t\tsubgraph "cluster_%s_shortcuts" {\n' "$item"
666252995Sdteske		printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_shortcuts"
667252995Sdteske		printf '\t\t\tlabel = "%s";\n' "$msg_shortcuts"
668252995Sdteske		awk '/^menu_selection="/ {
669252995Sdteske			sub(/^.*="/, "")
670252995Sdteske			sub(/\|.*/, "")
671252995Sdteske			printf "\t\t\t\"bsdconfig %s\";\n", $0
672252995Sdteske		}' "$INDEX"
673252995Sdteske		printf '\t\t};\n'
674252995Sdteske	fi
675252995Sdteske
676252995Sdteske	end_nodelist
677252995Sdteskedone
678252995Sdteske
679252995Sdteskeprintf '\n};\n'
680252995Sdteske
681252995Sdteske################################################################################
682252995Sdteske# END
683252995Sdteske################################################################################
684