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