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 112BEGIN \ 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 304function basename (file) \ 305{ 306 gsub(/[^\/]+\//, "", file); 307 return file; 308} 309 310function 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 326function 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 340function 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 354function err(msg) \ 355{ 356 printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr"; 357 exit 1; 358} 359 360function errx(msg) \ 361{ 362 printf("parselist: %s.\n", msg) >"/dev/stderr"; 363 exit 1; 364} 365