1# $NetBSD: parselist.awk,v 1.16 2009/04/10 16:16:12 apb 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 105BEGIN \ 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" 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" 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 297function basename (file) \ 298{ 299 gsub(/[^\/]+\//, "", file); 300 return file; 301} 302 303function 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 320function 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 335function 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 349function err(msg) \ 350{ 351 printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr"; 352 exit 1; 353} 354 355function errx(msg) \ 356{ 357 printf("parselist: %s.\n", msg) >"/dev/stderr"; 358 exit 1; 359} 360