Home | History | Annotate | Line # | Download | only in common
parselist.awk revision 1.9
      1 #	$NetBSD: parselist.awk,v 1.9 2002/03/14 22:26:09 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, the directories in src
     82 #					are listed first.
     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 
    103 BEGIN \
    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 
    287 function basename (file) \
    288 {
    289 	gsub(/[^\/]+\//, "", file);
    290 	return file;
    291 }
    292 
    293 function 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 
    306 function 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 
    316 function 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 
    327 function err(msg) \
    328 {
    329 	printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr";
    330 	exit 1;
    331 }
    332 
    333 function errx(msg) \
    334 {
    335 	printf("parselist: %s.\n", msg) >"/dev/stderr";
    336 	exit 1;
    337 }
    338