xref: /netbsd/distrib/common/parselist.awk (revision bf9ec67e)
1#	$NetBSD: parselist.awk,v 1.10 2002/04/10 02:01:43 lukem Exp $
2#
3# Copyright (c) 2002 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# This code is derived from software contributed to The NetBSD Foundation
7# by Luke Mewburn of Wasabi Systems.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17# 3. All advertising materials mentioning features or use of this software
18#    must display the following acknowledgement:
19#        This product includes software developed by the NetBSD
20#        Foundation, Inc. and its contributors.
21# 4. Neither the name of The NetBSD Foundation nor the names of its
22#    contributors may be used to endorse or promote products derived
23#    from this software without specific prior written permission.
24#
25# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35# POSSIBILITY OF SUCH DAMAGE.
36#
37
38#
39# awk -f parselist.awk -v mode=MODE [var=val ...] file1 [...]
40#
41#	Parse list files file1 [...], generating different output,
42#	depending upon the value of MODE:
43#
44#	    crunch	crunchgen(1) config
45#
46#	    mtree	mtree(8) specfile
47#
48#	    populate	sh(1) commands to populate ${TARGETDIR} from ${CURDIR}
49#			The following environment variables need to be set:
50#			    CRUNCHBIN	Name of crunchgen(1) target binary
51#			    CURDIR	Source directory; make(1)'s ${.CURDIR}
52#			    OBJDIR	Object directory; make(1)'s ${.OBJDIR}
53#			    TARGETDIR	Directory to populate
54#
55#
56# 	Each line of the input is either a comment (starts with `#'),
57#	or contains one of the following keywords and arguments.
58#
59#	Before each line is parsed for a keyword, words surrounded by
60#	"${" and "}", and containing only letters, numbers, and `_'
61#	will be replaced by the value of the environment variable of
62#	the same name.  I.e., "${MACHINE_ARCH}" will be replaced with the
63#	value of ENVIRON["MACHINE_ARCH"].
64#
65#	mode key	operation
66#	--------	---------
67#	C		crunch
68#	M		mtree
69#	P		populate
70#
71#	mode	keyword arg1 [...]	description
72#	----	------------------	-----------
73#
74#	C	ARGVLN	prog link	as per crunchgen(1) `ln'
75#
76#	P	CMD	arg1 [...]	run CMD as a shell command
77#
78#	M P	COPY	src dest [mode]	copy src to dest
79#
80#	M P	COPYDIR	src dest	recursively copy files under src to
81#					dest.  for M, dest is listed first,
82#					followed by the subdirectories in src.
83#
84#	C	LIBS	libspec ...	as per crunchgen(1) `libs'
85#
86#	M P	LINK	src d1 [d2 ...]	hard link src to d1, d2, ...
87#
88#	M	MTREE	arg1 [...]	output arguments `as-is' to specfile
89#
90#	C M P	PROG	prog [links...]	program(s) to crunch/mtree/populate.
91#					for M and P, the first prog listed
92#					is copied from ${OBJDIR}/${CRUNCHBIN}
93#					and then used as the name to link
94#					all other PROG entries to.
95#
96#	C	SPECIAL	prog cmd ...	as per crunchgen(1) `special'
97#
98#	C	SRCDIRS	dirname ...	as per crunchgen(1) `srcdirs'
99#
100#	M P	SYMLINK src dest [...]	symlink src to dest, [...]
101#
102
103BEGIN \
104{
105	crunchprog = "";
106
107	if (mode != "crunch" && mode != "mtree" && mode != "populate")
108		errx("Unknown parselist mode '" mode "'");
109
110	if (mode == "populate") {
111		split("CRUNCHBIN CURDIR OBJDIR TARGETDIR", needvars);
112		for (nv in needvars) {
113			if (! (needvars[nv] in ENVIRON))
114				errx("Environment variable " \
115				    needvars[nv] " not defined");
116		}
117	}
118
119	print "#";
120	print "# This file is automatically generated by";
121	print "#\tparselist mode=" mode;
122	print "#";
123	print "";
124	if (mode == "populate") {
125		print "cd " ENVIRON["CURDIR"];
126		print;
127	} else if (mode == "mtree") {
128		print "/unset\tall";
129		print "/set\ttype=file uname=root gname=wheel";
130		print;
131	}
132}
133
134/^$/ || /^#/ \
135{
136	print;
137	next;
138}
139
140#	replace ${FOO} with ENVIRON["FOO"]
141#
142/\${[A-Za-z0-9_]+}/ \
143{
144	while (match($0, /\${[A-Za-z0-9_]+}/) > 0) {
145		v = substr($0, RSTART + 2, RLENGTH - 3);
146		if (! (v in ENVIRON))
147			err("Variable " v " is not in the environment");
148		else
149			sub(/\${[A-Za-z0-9_]+}/, ENVIRON[v]);
150	}
151}
152
153$1 == "COPY" \
154{
155	if (NF < 3 || NF > 4)
156		err("Usage: COPY src dest [mode]");
157	if (mode == "populate" || mode == "mtree")
158		copy($2, $3, $4);
159	next;
160}
161
162$1 == "COPYDIR" \
163{
164	if (NF != 3)
165		err("Usage: COPYDIR src dest");
166	srcdir=$2;
167	destdir=$3;
168	if (mode == "mtree") {
169		printf("./%s type=dir mode=755\n", destdir);
170		command="cd " srcdir " && find . -type d -print"
171		while (command | getline dir) {
172			gsub(/^\.\//, "", dir);
173			if (dir == ".")
174				continue;
175			printf("./%s/%s type=dir mode=755\n", destdir, dir);
176		}
177		close(command);
178	}
179	if (mode == "populate" || mode == "mtree") {
180		command="cd " srcdir " && find . -type f -print"
181		while (command | getline srcfile) {
182			gsub(/^\.\//, "", srcfile);
183			copy(srcdir "/" srcfile, destdir "/" srcfile, "");
184		}
185		close(command);
186	}
187	next;
188}
189
190$1 == "LIBS" || $1 == "SPECIAL" || $1 == "SRCDIRS" \
191{
192	if (NF < 2)
193		err("Usage: " $1 " args...");
194	if (mode == "crunch") {
195		$1 = tolower($1);
196		print;
197	}
198	next;
199}
200
201$1 == "PROG" \
202{
203	if (NF < 2)
204		err("Usage: PROG prog [link ...]");
205	if (mode == "crunch") {
206		prog = basename($2);
207		print "progs " prog;
208		for (i = 3; i <= NF; i++)
209			print "ln " prog " " basename($i);
210	} else {
211		for (i = 2; i <= NF; i++) {
212			if (crunchprog == "") {
213				crunchprog = $i;
214				copy(ENVIRON["OBJDIR"] "/" ENVIRON["CRUNCHBIN"],
215				    crunchprog);
216				continue;
217			}
218			link(crunchprog, $i);
219		}
220	}
221	next;
222}
223
224$1 == "ARGVLN" \
225{
226	if (NF != 3)
227		err("Usage: ARGVLN prog link");
228	if (mode == "crunch") {
229		$1 = "ln";
230		print;
231	}
232	next;
233}
234
235$1 == "LINK" \
236{
237	if (NF < 3)
238		err("Usage: LINK prog link [...]");
239	if (mode == "populate" || mode == "mtree") {
240		for (i = 3; i <= NF; i++)
241			link($2, $i);
242	}
243	next;
244}
245
246$1 == "SYMLINK" \
247{
248	if (NF < 3)
249		err("Usage: SYMLINK prog link [...]");
250	if (mode == "populate" || mode == "mtree") {
251		for (i = 3; i <= NF; i++)
252			symlink($2, $i);
253	}
254	next;
255}
256
257$1 == "CMD" \
258{
259	if (NF < 2)
260		err("Usage: CMD ...");
261	if (mode == "populate") {
262		printf("(cd %s;", ENVIRON["TARGETDIR"]);
263		for (i = 2; i <= NF; i++)
264			printf(" %s", $i);
265		print ")";
266	}
267	next;
268}
269
270$1 == "MTREE" \
271{
272	if (NF < 2)
273		err("Usage: MTREE ...");
274	if (mode == "mtree") {
275		sub(/^[^ \t]+[ \t]+/, "");	# strip first word ("MTREE")
276		print;
277	}
278	next;
279}
280
281
282{
283	err("Unknown keyword '" $1 "'");
284}
285
286
287function basename (file) \
288{
289	gsub(/[^\/]+\//, "", file);
290	return file;
291}
292
293function copy (src, dest, perm) \
294{
295	if (mode == "mtree") {
296		printf("./%s%s\n", dest, perm != "" ? " mode=" perm : "");
297	} else {
298		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
299		printf("cp %s %s/%s\n", src, ENVIRON["TARGETDIR"], dest);
300		if (perm != "")
301			printf("chmod %s %s/%s\n", perm,
302			    ENVIRON["TARGETDIR"], dest);
303	}
304}
305
306function link (src, dest) \
307{
308	if (mode == "mtree") {
309		printf("./%s\n", dest);
310	} else {
311		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
312		printf("(cd %s; ln %s %s)\n", ENVIRON["TARGETDIR"], src, dest);
313	}
314}
315
316function symlink (src, dest) \
317{
318	if (mode == "mtree") {
319		printf("./%s type=link link=%s\n", dest, src);
320	} else {
321		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
322		printf("(cd %s; ln -s %s %s)\n", ENVIRON["TARGETDIR"],
323		    src, dest);
324	}
325}
326
327function err(msg) \
328{
329	printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr";
330	exit 1;
331}
332
333function errx(msg) \
334{
335	printf("parselist: %s.\n", msg) >"/dev/stderr";
336	exit 1;
337}
338