Home | History | Annotate | Line # | Download | only in common
parselist.awk revision 1.14
      1 #	$NetBSD: parselist.awk,v 1.14 2002/09/16 02:13:16 thorpej 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 #	    install	make(1) Makefile to install commands into ${TARGETDIR},
     47 #			with an `install' target.
     48 #			The following environment variables need to be set:
     49 #			    TARGETDIR	Directory to populate
     50 #
     51 #	    mtree	mtree(8) specfile
     52 #
     53 #	    populate	sh(1) commands to populate ${TARGETDIR} from ${CURDIR}
     54 #			The following environment variables need to be set:
     55 #			    CURDIR	Source directory; make(1)'s ${.CURDIR}
     56 #			    TARGETDIR	Directory to populate
     57 #
     58 #	The following environment variables need to be set for all modes:
     59 #	    CRUNCHBIN	Name of crunchgen(1) target binary
     60 #	    OBJDIR	Object directory; make(1)'s ${.OBJDIR}
     61 #
     62 # 	Each line of the input is either a comment (starts with `#'),
     63 #	or contains one of the following keywords and arguments.
     64 #
     65 #	Before each line is parsed for a keyword, words surrounded by
     66 #	"${" and "}", and containing only letters, numbers, and `_'
     67 #	will be replaced by the value of the environment variable of
     68 #	the same name.  I.e., "${MACHINE_ARCH}" will be replaced with the
     69 #	value of ENVIRON["MACHINE_ARCH"].
     70 #
     71 #	mode key	operation
     72 #	--------	---------
     73 #	C		crunch
     74 #	I		install
     75 #	M		mtree
     76 #	P		populate
     77 #
     78 #	mode	keyword arg1 [...]	description
     79 #	----	------------------	-----------
     80 #
     81 #	C	ARGVLN	prog link	as per crunchgen(1) `ln'
     82 #
     83 #	P	CMD	arg1 [...]	run CMD as a shell command
     84 #
     85 #	IMP	COPY	src dest [perm]	copy src to dest. perm defaults to 0444
     86 #
     87 #	IMP	COPYDIR	src dest	recursively copy files under src to
     88 #					dest.  for M, dest is listed first,
     89 #					followed by the subdirectories in src.
     90 #					copied directories have mode 0755.
     91 #					copied files have mode 0444.
     92 #
     93 #	C	LIBS	libspec ...	as per crunchgen(1) `libs'
     94 #
     95 #	IMP	LINK	src d1 [d2 ...]	hard link src to d1, d2, ...
     96 #
     97 #	M	MTREE	arg1 [...]	output arguments `as-is' to specfile
     98 #
     99 #	CIMP	PROG	prog [links...]	program(s) to crunch/mtree/populate.
    100 #					for I, M & P, the first prog listed
    101 #					is copied from ${OBJDIR}/${CRUNCHBIN}
    102 #					and then used as the name to link
    103 #					all other PROG entries to.
    104 #
    105 #	C	SPECIAL	prog cmd ...	as per crunchgen(1) `special'
    106 #
    107 #	C	SRCDIRS	dirname ...	as per crunchgen(1) `srcdirs'
    108 #
    109 #	IMP	SYMLINK src dest [...]	symlink src to dest, [...]
    110 #
    111 
    112 BEGIN \
    113 {
    114 	crunchprog = "";
    115 
    116 	if (mode != "crunch" && mode != "install" &&
    117 	    mode != "mtree" && mode != "populate")
    118 		errx("Unknown parselist mode '" mode "'");
    119 
    120 	needvars["CRUNCHBIN"]++
    121 	needvars["OBJDIR"]++
    122 	if (mode == "install") {
    123 		needvars["TARGETDIR"]++
    124 	}
    125 	else if (mode == "populate") {
    126 		needvars["CURDIR"]++
    127 	}
    128 	for (nv in needvars) {
    129 		if (! (nv in ENVIRON))
    130 			errx("Environment variable " nv " not defined");
    131 	}
    132 
    133 	print "#";
    134 	print "# This file is automatically generated by";
    135 	print "#\tparselist mode=" mode;
    136 	print "#";
    137 	print "";
    138 	if (mode == "install") {
    139 		print ".include <bsd.own.mk>"
    140 		print "install:"
    141 	} else if (mode == "mtree") {
    142 		print "/unset\tall";
    143 		print "/set\ttype=file uname=root gname=wheel";
    144 		print;
    145 	} else if (mode == "populate") {
    146 		print "cd " ENVIRON["CURDIR"];
    147 		print;
    148 	}
    149 }
    150 
    151 /^$/ || /^#/ \
    152 {
    153 	print;
    154 	next;
    155 }
    156 
    157 #	replace ${FOO} with ENVIRON["FOO"]
    158 #
    159 /\$\{[A-Za-z0-9_]+\}/ \
    160 {
    161 	while (match($0, /\$\{[A-Za-z0-9_]+\}/) > 0) {
    162 		v = substr($0, RSTART + 2, RLENGTH - 3);
    163 		if (! (v in ENVIRON))
    164 			err("Variable " v " is not in the environment");
    165 		else
    166 			sub(/\$\{[A-Za-z0-9_]+\}/, ENVIRON[v]);
    167 	}
    168 }
    169 
    170 $1 == "COPY" \
    171 {
    172 	if (NF < 3 || NF > 4)
    173 		err("Usage: COPY src dest [perm]");
    174 	if (mode == "install" || mode == "mtree" || mode == "populate")
    175 		copy($2, $3, $4);
    176 	next;
    177 }
    178 
    179 $1 == "COPYDIR" \
    180 {
    181 	if (NF != 3)
    182 		err("Usage: COPYDIR src dest");
    183 	srcdir=$2;
    184 	destdir=$3;
    185 	if (mode == "mtree") {
    186 		printf("./%s type=dir mode=755\n", destdir);
    187 		command="cd " srcdir " && find . -type d -print"
    188 		while (command | getline dir) {
    189 			gsub(/^\.\//, "", dir);
    190 			if (dir == ".")
    191 				continue;
    192 			printf("./%s/%s type=dir mode=755\n", destdir, dir);
    193 		}
    194 		close(command);
    195 	}
    196 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    197 		command="cd " srcdir " && find . -type f -print"
    198 		while (command | getline srcfile) {
    199 			gsub(/^\.\//, "", srcfile);
    200 			copy(srcdir "/" srcfile, destdir "/" srcfile, "");
    201 		}
    202 		close(command);
    203 	}
    204 	next;
    205 }
    206 
    207 $1 == "LIBS" || $1 == "SPECIAL" || $1 == "SRCDIRS" \
    208 {
    209 	if (NF < 2)
    210 		err("Usage: " $1 " args...");
    211 	if (mode == "crunch") {
    212 		$1 = tolower($1);
    213 		print;
    214 	}
    215 	next;
    216 }
    217 
    218 $1 == "PROG" \
    219 {
    220 	if (NF < 2)
    221 		err("Usage: PROG prog [link ...]");
    222 	if (mode == "crunch") {
    223 		prog = basename($2);
    224 		print "progs " prog;
    225 		for (i = 3; i <= NF; i++)
    226 			print "ln " prog " " basename($i);
    227 	} else {
    228 		for (i = 2; i <= NF; i++) {
    229 			if (crunchprog == "") {
    230 				crunchprog = $i;
    231 				copy(ENVIRON["OBJDIR"] "/" ENVIRON["CRUNCHBIN"],
    232 				    crunchprog, 555);
    233 				continue;
    234 			}
    235 			link(crunchprog, $i);
    236 		}
    237 	}
    238 	next;
    239 }
    240 
    241 $1 == "ARGVLN" \
    242 {
    243 	if (NF != 3)
    244 		err("Usage: ARGVLN prog link");
    245 	if (mode == "crunch") {
    246 		$1 = "ln";
    247 		print;
    248 	}
    249 	next;
    250 }
    251 
    252 $1 == "LINK" \
    253 {
    254 	if (NF < 3)
    255 		err("Usage: LINK prog link [...]");
    256 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    257 		for (i = 3; i <= NF; i++)
    258 			link($2, $i);
    259 	}
    260 	next;
    261 }
    262 
    263 $1 == "SYMLINK" \
    264 {
    265 	if (NF < 3)
    266 		err("Usage: SYMLINK prog link [...]");
    267 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    268 		for (i = 3; i <= NF; i++)
    269 			symlink($2, $i);
    270 	}
    271 	next;
    272 }
    273 
    274 $1 == "CMD" \
    275 {
    276 	if (NF < 2)
    277 		err("Usage: CMD ...");
    278 	if (mode == "populate") {
    279 		printf("(cd %s;", ENVIRON["TARGETDIR"]);
    280 		for (i = 2; i <= NF; i++)
    281 			printf(" %s", $i);
    282 		print ") || exit 1";
    283 	}
    284 	next;
    285 }
    286 
    287 $1 == "MTREE" \
    288 {
    289 	if (NF < 2)
    290 		err("Usage: MTREE ...");
    291 	if (mode == "mtree") {
    292 		sub(/^[^ \t]+[ \t]+/, "");	# strip first word ("MTREE")
    293 		print;
    294 	}
    295 	next;
    296 }
    297 
    298 
    299 {
    300 	err("Unknown keyword '" $1 "'");
    301 }
    302 
    303 
    304 function basename (file) \
    305 {
    306 	gsub(/[^\/]+\//, "", file);
    307 	return file;
    308 }
    309 
    310 function copy (src, dest, perm) \
    311 {
    312 	if (perm == "")
    313 		perm = 444;
    314 	if (mode == "install") {
    315 		printf("\t${INSTALL_FILE} -o ${BINOWN} -g ${BINGRP} -m %s %s %s/%s\n",
    316 		    perm, src, ENVIRON["TARGETDIR"], dest)
    317 	} else if (mode == "mtree") {
    318 		printf("./%s mode=%s\n", dest, perm);
    319 	} else {
    320 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    321 		printf("cp %s %s/%s\n", src, ENVIRON["TARGETDIR"], dest);
    322 		printf("chmod %s %s/%s\n", perm, ENVIRON["TARGETDIR"], dest);
    323 	}
    324 }
    325 
    326 function link (src, dest) \
    327 {
    328 	if (mode == "install") {
    329 		printf("\t${INSTALL_LINK} %s/%s %s/%s\n",
    330 		    ENVIRON["TARGETDIR"], src, ENVIRON["TARGETDIR"], dest)
    331 	} else if (mode == "mtree") {
    332 		printf("./%s\n", dest);
    333 	} else {
    334 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    335 		printf("(cd %s; ln %s %s) || exit 1\n",
    336 		    ENVIRON["TARGETDIR"], src, dest);
    337 	}
    338 }
    339 
    340 function symlink (src, dest) \
    341 {
    342 	if (mode == "install") {
    343 		printf("\t${INSTALL_SYMLINK} %s/%s %s/%s\n",
    344 		    ENVIRON["TARGETDIR"], src, ENVIRON["TARGETDIR"], dest)
    345 	} else if (mode == "mtree") {
    346 		printf("./%s type=link link=%s\n", dest, src);
    347 	} else {
    348 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    349 		printf("(cd %s; ln -s %s %s) || exit 1\n",
    350 		    ENVIRON["TARGETDIR"], src, dest);
    351 	}
    352 }
    353 
    354 function err(msg) \
    355 {
    356 	printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr";
    357 	exit 1;
    358 }
    359 
    360 function errx(msg) \
    361 {
    362 	printf("parselist: %s.\n", msg) >"/dev/stderr";
    363 	exit 1;
    364 }
    365