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