• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#! /bin/sh
2#
3# SPDX-License-Identifier: BSD-2-Clause
4#
5# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11#   list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14#   this list of conditions and the following disclaimer in the documentation
15#   and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27# POSSIBILITY OF SUCH DAMAGE.
28#
29
30# Print the usage and exit with an error.
31usage() {
32	printf "usage: %s manpage\n" "$0" 1>&2
33	exit 1
34}
35
36# Generate a manpage and print it to a file.
37# @param md   The markdown manual to generate a manpage for.
38# @param out  The file to print the manpage to.
39gen_manpage() {
40
41	_gen_manpage_md="$1"
42	shift
43
44	_gen_manpage_out="$1"
45	shift
46
47	cat "$manualsdir/header.txt" > "$_gen_manpage_out"
48	cat "$manualsdir/header_${manpage}.txt" >> "$_gen_manpage_out"
49
50	pandoc -f commonmark_x -t man "$_gen_manpage_md" >> "$_gen_manpage_out"
51}
52
53# Generate a manual from a template and print it to a file before generating
54# its manpage.
55# param args  The type of markdown manual to generate. This is a string that
56#             corresponds to build type (see the Build Type section of the
57#             manuals/build.md manual).
58gen_manual() {
59
60	_gen_manual_args="$1"
61	shift
62
63	# Set up some local variables. $manualsdir and $manpage from from the
64	# variables outside the function.
65	_gen_manual_status="$ALL"
66	_gen_manual_out="$manualsdir/$manpage/$_gen_manual_args.1"
67	_gen_manual_md="$manualsdir/$manpage/$_gen_manual_args.1.md"
68	_gen_manual_temp="$manualsdir/temp.1.md"
69
70	# We need to set IFS, so we store it here for restoration later.
71	_gen_manual_ifs="$IFS"
72
73	# Remove the files that will be generated.
74	rm -rf "$_gen_manual_out" "$_gen_manual_md"
75
76	# Here is the magic. This loop reads the template line-by-line, and based on
77	# _gen_manual_status, either prints it to the markdown manual or not.
78	#
79	# Here is how the template is set up: it is a normal markdown file except
80	# that there are sections surrounded tags that look like this:
81	#
82	# {{ <build_type_list> }}
83	# ...
84	# {{ end }}
85	#
86	# Those tags mean that whatever build types are found in the
87	# <build_type_list> get to keep that section. Otherwise, skip.
88	#
89	# Obviously, the tag itself and its end are not printed to the markdown
90	# manual.
91	while IFS= read -r line; do
92
93		# If we have found an end, reset the status.
94		if [ "$line" = "{{ end }}" ]; then
95
96			# Some error checking. This helps when editing the templates.
97			if [ "$_gen_manual_status" -eq "$ALL" ]; then
98				err_exit "{{ end }} tag without corresponding start tag" 2
99			fi
100
101			_gen_manual_status="$ALL"
102
103		# We have found a tag that allows our build type to use it.
104		elif [ "${line#\{\{* $_gen_manual_args *\}\}}" != "$line" ]; then
105
106			# More error checking. We don't want tags nested.
107			if [ "$_gen_manual_status" -ne "$ALL" ]; then
108				err_exit "start tag nested in start tag" 3
109			fi
110
111			_gen_manual_status="$NOSKIP"
112
113		# We have found a tag that is *not* allowed for our build type.
114		elif [ "${line#\{\{*\}\}}" != "$line" ]; then
115
116			if [ "$_gen_manual_status" -ne "$ALL" ]; then
117				err_exit "start tag nested in start tag" 3
118			fi
119
120			_gen_manual_status="$SKIP"
121
122		# This is for normal lines. If we are not skipping, print.
123		else
124			if [ "$_gen_manual_status" -ne "$SKIP" ]; then
125				printf '%s\n' "$line" >> "$_gen_manual_temp"
126			fi
127		fi
128
129	done < "$manualsdir/${manpage}.1.md.in"
130
131	# Remove multiple blank lines.
132	uniq "$_gen_manual_temp" "$_gen_manual_md"
133
134	# Remove the temp file.
135	rm -rf "$_gen_manual_temp"
136
137	# Reset IFS.
138	IFS="$_gen_manual_ifs"
139
140	# Generate the manpage.
141	gen_manpage "$_gen_manual_md" "$_gen_manual_out"
142}
143
144set -e
145
146script="$0"
147scriptdir=$(dirname "$script")
148manualsdir="$scriptdir/../manuals"
149
150. "$scriptdir/functions.sh"
151
152# Constants for use later. If the set of build types is changed, $ARGS must be
153# updated.
154ARGS="A E H N EH EN HN EHN"
155ALL=0
156NOSKIP=1
157SKIP=2
158
159# Process command-line arguments.
160test "$#" -eq 1 || usage
161
162manpage="$1"
163shift
164
165if [ "$manpage" != "bcl" ]; then
166
167	# Generate a manual and manpage for each build type.
168	for a in $ARGS; do
169		gen_manual "$a"
170	done
171
172else
173	# For bcl, just generate the manpage.
174	gen_manpage "$manualsdir/${manpage}.3.md" "$manualsdir/${manpage}.3"
175fi
176