parselist.awk revision 1.11 1 # $NetBSD: parselist.awk,v 1.11 2002/05/29 03:01:55 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 [perm] copy src to dest. perm defaults to 0444
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 # copied directories have mode 0755.
84 # copied files have mode 0444.
85 #
86 # C LIBS libspec ... as per crunchgen(1) `libs'
87 #
88 # M P LINK src d1 [d2 ...] hard link src to d1, d2, ...
89 #
90 # M MTREE arg1 [...] output arguments `as-is' to specfile
91 #
92 # C M P PROG prog [links...] program(s) to crunch/mtree/populate.
93 # for M and 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 # M P SYMLINK src dest [...] symlink src to dest, [...]
103 #
104
105 BEGIN \
106 {
107 crunchprog = "";
108
109 if (mode != "crunch" && mode != "mtree" && mode != "populate")
110 errx("Unknown parselist mode '" mode "'");
111
112 if (mode == "populate") {
113 split("CRUNCHBIN CURDIR OBJDIR TARGETDIR", needvars);
114 for (nv in needvars) {
115 if (! (needvars[nv] in ENVIRON))
116 errx("Environment variable " \
117 needvars[nv] " not defined");
118 }
119 }
120
121 print "#";
122 print "# This file is automatically generated by";
123 print "#\tparselist mode=" mode;
124 print "#";
125 print "";
126 if (mode == "populate") {
127 print "cd " ENVIRON["CURDIR"];
128 print;
129 } else if (mode == "mtree") {
130 print "/unset\tall";
131 print "/set\ttype=file uname=root gname=wheel";
132 print;
133 }
134 }
135
136 /^$/ || /^#/ \
137 {
138 print;
139 next;
140 }
141
142 # replace ${FOO} with ENVIRON["FOO"]
143 #
144 /\${[A-Za-z0-9_]+}/ \
145 {
146 while (match($0, /\${[A-Za-z0-9_]+}/) > 0) {
147 v = substr($0, RSTART + 2, RLENGTH - 3);
148 if (! (v in ENVIRON))
149 err("Variable " v " is not in the environment");
150 else
151 sub(/\${[A-Za-z0-9_]+}/, ENVIRON[v]);
152 }
153 }
154
155 $1 == "COPY" \
156 {
157 if (NF < 3 || NF > 4)
158 err("Usage: COPY src dest [perm]");
159 if (mode == "populate" || mode == "mtree")
160 copy($2, $3, $4);
161 next;
162 }
163
164 $1 == "COPYDIR" \
165 {
166 if (NF != 3)
167 err("Usage: COPYDIR src dest");
168 srcdir=$2;
169 destdir=$3;
170 if (mode == "mtree") {
171 printf("./%s type=dir mode=755\n", destdir);
172 command="cd " srcdir " && find . -type d -print"
173 while (command | getline dir) {
174 gsub(/^\.\//, "", dir);
175 if (dir == ".")
176 continue;
177 printf("./%s/%s type=dir mode=755\n", destdir, dir);
178 }
179 close(command);
180 }
181 if (mode == "populate" || mode == "mtree") {
182 command="cd " srcdir " && find . -type f -print"
183 while (command | getline srcfile) {
184 gsub(/^\.\//, "", srcfile);
185 copy(srcdir "/" srcfile, destdir "/" srcfile, "");
186 }
187 close(command);
188 }
189 next;
190 }
191
192 $1 == "LIBS" || $1 == "SPECIAL" || $1 == "SRCDIRS" \
193 {
194 if (NF < 2)
195 err("Usage: " $1 " args...");
196 if (mode == "crunch") {
197 $1 = tolower($1);
198 print;
199 }
200 next;
201 }
202
203 $1 == "PROG" \
204 {
205 if (NF < 2)
206 err("Usage: PROG prog [link ...]");
207 if (mode == "crunch") {
208 prog = basename($2);
209 print "progs " prog;
210 for (i = 3; i <= NF; i++)
211 print "ln " prog " " basename($i);
212 } else {
213 for (i = 2; i <= NF; i++) {
214 if (crunchprog == "") {
215 crunchprog = $i;
216 copy(ENVIRON["OBJDIR"] "/" ENVIRON["CRUNCHBIN"],
217 crunchprog, 555);
218 continue;
219 }
220 link(crunchprog, $i);
221 }
222 }
223 next;
224 }
225
226 $1 == "ARGVLN" \
227 {
228 if (NF != 3)
229 err("Usage: ARGVLN prog link");
230 if (mode == "crunch") {
231 $1 = "ln";
232 print;
233 }
234 next;
235 }
236
237 $1 == "LINK" \
238 {
239 if (NF < 3)
240 err("Usage: LINK prog link [...]");
241 if (mode == "populate" || mode == "mtree") {
242 for (i = 3; i <= NF; i++)
243 link($2, $i);
244 }
245 next;
246 }
247
248 $1 == "SYMLINK" \
249 {
250 if (NF < 3)
251 err("Usage: SYMLINK prog link [...]");
252 if (mode == "populate" || mode == "mtree") {
253 for (i = 3; i <= NF; i++)
254 symlink($2, $i);
255 }
256 next;
257 }
258
259 $1 == "CMD" \
260 {
261 if (NF < 2)
262 err("Usage: CMD ...");
263 if (mode == "populate") {
264 printf("(cd %s;", ENVIRON["TARGETDIR"]);
265 for (i = 2; i <= NF; i++)
266 printf(" %s", $i);
267 print ") || exit 1";
268 }
269 next;
270 }
271
272 $1 == "MTREE" \
273 {
274 if (NF < 2)
275 err("Usage: MTREE ...");
276 if (mode == "mtree") {
277 sub(/^[^ \t]+[ \t]+/, ""); # strip first word ("MTREE")
278 print;
279 }
280 next;
281 }
282
283
284 {
285 err("Unknown keyword '" $1 "'");
286 }
287
288
289 function basename (file) \
290 {
291 gsub(/[^\/]+\//, "", file);
292 return file;
293 }
294
295 function copy (src, dest, perm) \
296 {
297 if (perm == "")
298 perm = 444;
299 if (mode == "mtree") {
300 printf("./%s mode=%s\n", dest, perm);
301 } else {
302 printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
303 printf("cp %s %s/%s\n", src, ENVIRON["TARGETDIR"], dest);
304 printf("chmod %s %s/%s\n", perm, ENVIRON["TARGETDIR"], dest);
305 }
306 }
307
308 function link (src, dest) \
309 {
310 if (mode == "mtree") {
311 printf("./%s\n", dest);
312 } else {
313 printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
314 printf("(cd %s; ln %s %s) || exit 1\n",
315 ENVIRON["TARGETDIR"], src, dest);
316 }
317 }
318
319 function symlink (src, dest) \
320 {
321 if (mode == "mtree") {
322 printf("./%s type=link link=%s\n", dest, src);
323 } else {
324 printf("rm -rf %s/%s\n", ENVIRON["TARGETDIR"], dest);
325 printf("(cd %s; ln -s %s %s) || exit 1\n",
326 ENVIRON["TARGETDIR"], src, dest);
327 }
328 }
329
330 function err(msg) \
331 {
332 printf("parselist: %s at line %d of input.\n", msg, NR) >"/dev/stderr";
333 exit 1;
334 }
335
336 function errx(msg) \
337 {
338 printf("parselist: %s.\n", msg) >"/dev/stderr";
339 exit 1;
340 }
341