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