1# $NetBSD: parselist.awk,v 1.10 2002/04/10 02:01:43 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, dest is listed first, 82# followed by the subdirectories in src. 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 103BEGIN \ 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 287function basename (file) \ 288{ 289 gsub(/[^\/]+\//, "", file); 290 return file; 291} 292 293function 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 306function 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 316function 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 327function err(msg) \ 328{ 329 printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr"; 330 exit 1; 331} 332 333function errx(msg) \ 334{ 335 printf("parselist: %s.\n", msg) >"/dev/stderr"; 336 exit 1; 337} 338