Home | History | Annotate | Line # | Download | only in common
      1 #	$NetBSD: parselist.awk,v 1.17 2024/04/16 23:40:36 christos 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 #
     18 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28 # POSSIBILITY OF SUCH DAMAGE.
     29 #
     30 
     31 #
     32 # awk -f parselist.awk -v mode=MODE [var=val ...] file1 [...]
     33 #
     34 #	Parse list files file1 [...], generating different output,
     35 #	depending upon the value of MODE:
     36 #
     37 #	    crunch	crunchgen(1) config
     38 #
     39 #	    install	make(1) Makefile to install commands into ${TARGETDIR},
     40 #			with an `install' target.
     41 #			The following environment variables need to be set:
     42 #			    TARGETDIR	Directory to populate
     43 #
     44 #	    mtree	mtree(8) specfile
     45 #
     46 #	    populate	sh(1) commands to populate ${TARGETDIR} from ${CURDIR}
     47 #			The following environment variables need to be set:
     48 #			    CURDIR	Source directory; make(1)'s ${.CURDIR}
     49 #			    TARGETDIR	Directory to populate
     50 #
     51 #	The following environment variables need to be set for all modes:
     52 #	    CRUNCHBIN	Name of crunchgen(1) target binary
     53 #	    OBJDIR	Object directory; make(1)'s ${.OBJDIR}
     54 #
     55 # 	Each line of the input is either a comment (starts with `#'),
     56 #	or contains one of the following keywords and arguments.
     57 #
     58 #	Before each line is parsed for a keyword, words surrounded by
     59 #	"${" and "}", and containing only letters, numbers, and `_'
     60 #	will be replaced by the value of the environment variable of
     61 #	the same name.  I.e., "${MACHINE_ARCH}" will be replaced with the
     62 #	value of ENVIRON["MACHINE_ARCH"].
     63 #
     64 #	mode key	operation
     65 #	--------	---------
     66 #	C		crunch
     67 #	I		install
     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 #	IMP	COPY	src dest [perm]	copy src to dest. perm defaults to 0444
     79 #
     80 #	IMP	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 #					copied directories have mode 0755.
     84 #					copied files have mode 0444.
     85 #
     86 #	C	LIBS	libspec ...	as per crunchgen(1) `libs'
     87 #
     88 #	IMP	LINK	src d1 [d2 ...]	hard link src to d1, d2, ...
     89 #
     90 #	M	MTREE	arg1 [...]	output arguments `as-is' to specfile
     91 #
     92 #	CIMP	PROG	prog [links...]	program(s) to crunch/mtree/populate.
     93 #					for I, M & P, the first prog listed
     94 #					is copied from ${OBJDIR}/${CRUNCHBIN}
     95 #					and then used as the name to link
     96 #					all other PROG entries to.
     97 #
     98 #	C	SPECIAL	prog cmd ...	as per crunchgen(1) `special'
     99 #
    100 #	C	SRCDIRS	dirname ...	as per crunchgen(1) `srcdirs'
    101 #
    102 #	IMP	SYMLINK src dest [...]	symlink src to dest, [...]
    103 #
    104 
    105 BEGIN \
    106 {
    107 	crunchprog = "";
    108 
    109 	if (mode != "crunch" && mode != "install" &&
    110 	    mode != "mtree" && mode != "populate")
    111 		errx("Unknown parselist mode '" mode "'");
    112 
    113 	needvars["CRUNCHBIN"]++
    114 	needvars["OBJDIR"]++
    115 	if (mode == "install") {
    116 		needvars["TARGETDIR"]++
    117 	}
    118 	else if (mode == "populate") {
    119 		needvars["CURDIR"]++
    120 	}
    121 	for (nv in needvars) {
    122 		if (! (nv in ENVIRON))
    123 			errx("Environment variable " nv " not defined");
    124 	}
    125 
    126 	print "#";
    127 	print "# This file is automatically generated by";
    128 	print "#\tparselist mode=" mode;
    129 	print "#";
    130 	print "";
    131 	if (mode == "install") {
    132 		print ".include <bsd.own.mk>"
    133 		print "install:"
    134 	} else if (mode == "mtree") {
    135 		print "/unset\tall";
    136 		print "/set\ttype=file uname=root gname=wheel";
    137 		print;
    138 	} else if (mode == "populate") {
    139 		print "cd " ENVIRON["CURDIR"];
    140 		print;
    141 	}
    142 }
    143 
    144 /^$/ || /^#/ \
    145 {
    146 	print;
    147 	next;
    148 }
    149 
    150 #	replace ${FOO} with ENVIRON["FOO"]
    151 #
    152 /\$\{[A-Za-z0-9_]+\}/ \
    153 {
    154 	while (match($0, /\$\{[A-Za-z0-9_]+\}/) > 0) {
    155 		v = substr($0, RSTART + 2, RLENGTH - 3);
    156 		if (! (v in ENVIRON))
    157 			err("Variable " v " is not in the environment");
    158 		else
    159 			sub(/\$\{[A-Za-z0-9_]+\}/, ENVIRON[v]);
    160 	}
    161 }
    162 
    163 $1 == "COPY" \
    164 {
    165 	if (NF < 3 || NF > 4)
    166 		err("Usage: COPY src dest [perm]");
    167 	if (mode == "install" || mode == "mtree" || mode == "populate")
    168 		copy($2, $3, $4);
    169 	next;
    170 }
    171 
    172 $1 == "COPYDIR" \
    173 {
    174 	if (NF != 3)
    175 		err("Usage: COPYDIR src dest");
    176 	srcdir=$2;
    177 	destdir=$3;
    178 	if (mode == "mtree") {
    179 		printf("./%s type=dir mode=755\n", destdir);
    180 		command="cd " srcdir " && find . -type d -print | LC_ALL=C sort"
    181 		while (command | getline dir) {
    182 			gsub(/^\.\//, "", dir);
    183 			if (dir == ".")
    184 				continue;
    185 			printf("./%s/%s type=dir mode=755\n", destdir, dir);
    186 		}
    187 		close(command);
    188 	}
    189 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    190 		command="cd " srcdir " && find . -type f -print | LC_ALL=C sort"
    191 		while (command | getline srcfile) {
    192 			gsub(/^\.\//, "", srcfile);
    193 			copy(srcdir "/" srcfile, destdir "/" srcfile, "");
    194 		}
    195 		close(command);
    196 	}
    197 	next;
    198 }
    199 
    200 $1 == "LIBS" || $1 == "SPECIAL" || $1 == "SRCDIRS" \
    201 {
    202 	if (NF < 2)
    203 		err("Usage: " $1 " args...");
    204 	if (mode == "crunch") {
    205 		$1 = tolower($1);
    206 		print;
    207 	}
    208 	next;
    209 }
    210 
    211 $1 == "PROG" \
    212 {
    213 	if (NF < 2)
    214 		err("Usage: PROG prog [link ...]");
    215 	if (mode == "crunch") {
    216 		prog = basename($2);
    217 		print "progs " prog;
    218 		for (i = 3; i <= NF; i++)
    219 			print "ln " prog " " basename($i);
    220 	} else {
    221 		for (i = 2; i <= NF; i++) {
    222 			if (crunchprog == "") {
    223 				crunchprog = $i;
    224 				copy(ENVIRON["OBJDIR"] "/" ENVIRON["CRUNCHBIN"],
    225 				    crunchprog, 555);
    226 				continue;
    227 			}
    228 			link(crunchprog, $i, 555);
    229 		}
    230 	}
    231 	next;
    232 }
    233 
    234 $1 == "ARGVLN" \
    235 {
    236 	if (NF != 3)
    237 		err("Usage: ARGVLN prog link");
    238 	if (mode == "crunch") {
    239 		$1 = "ln";
    240 		print;
    241 	}
    242 	next;
    243 }
    244 
    245 $1 == "LINK" \
    246 {
    247 	if (NF < 3)
    248 		err("Usage: LINK prog link [...]");
    249 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    250 		for (i = 3; i <= NF; i++)
    251 			link($2, $i, 444);
    252 	}
    253 	next;
    254 }
    255 
    256 $1 == "SYMLINK" \
    257 {
    258 	if (NF < 3)
    259 		err("Usage: SYMLINK prog link [...]");
    260 	if (mode == "install" || mode == "mtree" || mode == "populate") {
    261 		for (i = 3; i <= NF; i++)
    262 			symlink($2, $i);
    263 	}
    264 	next;
    265 }
    266 
    267 $1 == "CMD" \
    268 {
    269 	if (NF < 2)
    270 		err("Usage: CMD ...");
    271 	if (mode == "populate") {
    272 		printf("(cd %s;", ENVIRON["TARGETDIR"]);
    273 		for (i = 2; i <= NF; i++)
    274 			printf(" %s", $i);
    275 		print ") || exit 1";
    276 	}
    277 	next;
    278 }
    279 
    280 $1 == "MTREE" \
    281 {
    282 	if (NF < 2)
    283 		err("Usage: MTREE ...");
    284 	if (mode == "mtree") {
    285 		sub(/^[^ \t]+[ \t]+/, "");	# strip first word ("MTREE")
    286 		print;
    287 	}
    288 	next;
    289 }
    290 
    291 
    292 {
    293 	err("Unknown keyword '" $1 "'");
    294 }
    295 
    296 
    297 function basename (file) \
    298 {
    299 	gsub(/[^\/]+\//, "", file);
    300 	return file;
    301 }
    302 
    303 function copy (src, dest, perm) \
    304 {
    305 	if (perm == "")
    306 		perm = 444;
    307 	if (mode == "install") {
    308 		printf("\t${INSTALL_FILE} -o ${BINOWN} -g ${BINGRP}" \
    309 		    " -m %s %s %s/%s\n",
    310 		    perm, src, ENVIRON["TARGETDIR"], dest)
    311 	} else if (mode == "mtree") {
    312 		printf("./%s mode=%s\n", dest, perm);
    313 	} else {
    314 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    315 		printf("cp %s %s/%s\n", src, ENVIRON["TARGETDIR"], dest);
    316 		printf("chmod %s %s/%s\n", perm, ENVIRON["TARGETDIR"], dest);
    317 	}
    318 }
    319 
    320 function link (src, dest, perm) \
    321 {
    322 	if (mode == "install") {
    323 		printf("\t${INSTALL_LINK} -o ${BINOWN} -g ${BINGRP}" \
    324 		    " -m %s %s/%s %s/%s\n",
    325 		    perm, ENVIRON["TARGETDIR"], src, ENVIRON["TARGETDIR"], dest)
    326 	} else if (mode == "mtree") {
    327 		printf("./%s mode=%s\n", dest, perm);
    328 	} else {
    329 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    330 		printf("(cd %s; ln %s %s) || exit 1\n",
    331 		    ENVIRON["TARGETDIR"], src, dest);
    332 	}
    333 }
    334 
    335 function symlink (src, dest) \
    336 {
    337 	if (mode == "install") {
    338 		printf("\t${INSTALL_SYMLINK} %s/%s %s/%s\n",
    339 		    ENVIRON["TARGETDIR"], src, ENVIRON["TARGETDIR"], dest)
    340 	} else if (mode == "mtree") {
    341 		printf("./%s type=link link=%s\n", dest, src);
    342 	} else {
    343 		printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
    344 		printf("(cd %s; ln -s %s %s) || exit 1\n",
    345 		    ENVIRON["TARGETDIR"], src, dest);
    346 	}
    347 }
    348 
    349 function err(msg) \
    350 {
    351 	printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr";
    352 	exit 1;
    353 }
    354 
    355 function errx(msg) \
    356 {
    357 	printf("parselist: %s.\n", msg) >"/dev/stderr";
    358 	exit 1;
    359 }
    360