1#! /bin/sh
2#	$NetBSD: mkinit.sh,v 1.10 2018/12/05 09:20:18 kre Exp $
3
4# Copyright (c) 2003 The NetBSD Foundation, Inc.
5# All rights reserved.
6#
7# This code is derived from software contributed to The NetBSD Foundation
8# by David Laight.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions
12# are met:
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18#
19# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31srcs="$*"
32
33# use of echo in this script is broken
34
35# some echo versions will expand \n in the args, which breaks C
36# Note: this script is a HOST_PROG ... it must run in the
37# build host's environment, with its shell.
38
39# Fortunately, use of echo here is also trivially simplistic,
40# we can easily replace all uses with ...
41
42echo()
43{
44	printf '%s\n' "$1"
45}
46
47# CAUTION: for anyone modifying this script.... use printf
48# rather than echo to output anything at all... then
49# you will avoid being bitten by the simplicity of this function.
50# This was done this way rather than wholesale replacement
51# to avoid unnecessary code churn.
52
53
54nl='
55'
56openparen='('
57
58# shells have bugs (including older NetBSD sh) in how \ is
59# used in pattern matching.   So work out what the shell
60# running this script expects.   We could also just use a
61# literal \ in the pattern, which would need to be quoted
62# of course, but then we'd run into a whole host of potential
63# other shell bugs (both with the quoting in the pattern, and
64# with the matching that follows if that works as inended).
65# Far easier, and more reliable, is to just work out what works,
66# and then use it, which more or less mandates using a variable...
67backslash='\\'
68var='abc\'			# dummy test case.
69if [ "$var" = "${var%$backslash}" ]
70then
71	# buggy sh, try the broken way
72	backslash='\'
73	if [ "$var" = "${var%$backslash}" ]
74	then
75		printf >&2 "$0: %s\n" 'No pattern match with \ (broken shell)'
76		exit 1
77	fi
78fi
79# We know we can detect the presence of a trailing \, which is all we need.
80# Now to confirm we will not generate false matches.
81var='abc'
82if [ "$var" != "${var%$backslash}" ]
83then
84	printf >&2 "$0: %s\n" 'Bogus pattern match with \ (broken shell)'
85	exit 1
86fi
87unset var
88
89includes=' "shell.h" "mystring.h" "init.h" '
90defines=
91decles=
92event_init=
93event_reset=
94event_shellproc=
95
96for src in $srcs; do
97	exec <$src
98	decnl="$nl"
99	while IFS=; read -r line; do
100		[ "$line" = x ]
101		case "$line " in
102		INIT["{ 	"]* ) event=init;;
103		RESET["{ 	"]* ) event=reset;;
104		SHELLPROC["{ 	"]* ) event=shellproc;;
105		INCLUDE[\ \	]* )
106			IFS=' 	'
107			set -- $line
108			# ignore duplicates
109			[ "${includes}" != "${includes% $2 *}" ] && continue
110			includes="$includes$2 "
111			continue
112			;;
113		MKINIT\  )
114			# struct declaration
115			decles="$decles$nl"
116			while
117				read -r line
118				decles="${decles}${line}${nl}"
119				[ "$line" != "};" ]
120			do
121				:
122			done
123			decnl="$nl"
124			continue
125			;;
126		MKINIT["{ 	"]* )
127			# strip initialiser
128			def=${line#MKINIT}
129			comment="${def#*;}"
130			def="${def%;$comment}"
131			def="${def%%=*}"
132			def="${def% }"
133			decles="${decles}${decnl}extern${def};${comment}${nl}"
134			decnl=
135			continue
136			;;
137		\#define[\ \	]* )
138			IFS=' 	'
139			set -- $line
140			# Ignore those with arguments
141			[ "$2" = "${2##*$openparen}" ] || continue
142			# and multiline definitions
143			[ "$line" = "${line%$backslash}" ] || continue
144			defines="${defines}#undef	$2${nl}${line}${nl}"
145			continue
146			;;
147		* ) continue;;
148		esac
149		# code for events
150		ev="${nl}	/* from $src: */${nl}	{${nl}"
151		# Indent the text by an extra <tab>
152		while
153			read -r line
154			[ "$line" != "}" ]
155		do
156			case "$line" in
157			('')	;;
158			('#'*)	;;
159			(*)	line="	$line";;
160			esac
161			ev="${ev}${line}${nl}"
162		done
163		ev="${ev}	}${nl}"
164		eval event_$event=\"\$event_$event\$ev\"
165	done
166done
167
168exec >init.c.tmp
169
170echo "/*"
171echo " * This file was generated by the mkinit program."
172echo " */"
173echo
174
175IFS=' '
176for f in $includes; do
177	echo "#include $f"
178done
179
180echo
181echo
182echo
183echo "$defines"
184echo
185echo "$decles"
186echo
187echo
188echo "/*"
189echo " * Initialization code."
190echo " */"
191echo
192echo "void"
193echo "init(void)"
194echo "{"
195echo "${event_init}"
196echo "}"
197echo
198echo
199echo
200echo "/*"
201echo " * This routine is called when an error or an interrupt occurs in an"
202echo " * interactive shell and control is returned to the main command loop."
203echo " */"
204echo
205echo "void"
206echo "reset(void)"
207echo "{"
208echo "${event_reset}"
209echo "}"
210echo
211echo
212echo
213echo "/*"
214echo " * This routine is called to initialize the shell to run a shell procedure."
215echo " */"
216echo
217echo "void"
218echo "initshellproc(void)"
219echo "{"
220echo "${event_shellproc}"
221echo "}"
222
223exec >&-
224mv init.c.tmp init.c
225