xref: /netbsd/sys/kern/vnode_if.sh (revision bf9ec67e)
1#!/bin/sh -
2copyright="\
3/*
4 * Copyright (c) 1992, 1993, 1994, 1995
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \`\`AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35"
36SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.30 2001/11/12 14:34:24 lukem Exp $'
37
38# Script to produce VFS front-end sugar.
39#
40# usage: vnode_if.sh srcfile
41#	(where srcfile is currently /sys/kern/vnode_if.src)
42#
43
44if [ $# -ne 1 ] ; then
45	echo 'usage: vnode_if.sh srcfile'
46	exit 1
47fi
48
49# Name and revision of the source file.
50src=$1
51SRC_ID=`head -1 $src | sed -e 's/.*\$\(.*\)\$.*/\1/'`
52
53# Names of the created files.
54out_c=vnode_if.c
55out_h=../sys/vnode_if.h
56
57# Awk program (must support nawk extensions)
58# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
59awk=${AWK:-awk}
60
61# Does this awk have a "toupper" function? (i.e. is it GNU awk)
62isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
63
64# If this awk does not define "toupper" then define our own.
65if [ "$isgawk" = TRUE ] ; then
66	# GNU awk provides it.
67	toupper=
68else
69	# Provide our own toupper()
70	toupper='
71function toupper(str) {
72	_toupper_cmd = "echo "str" |tr a-z A-Z"
73	_toupper_cmd | getline _toupper_str;
74	close(_toupper_cmd);
75	return _toupper_str;
76}'
77fi
78
79#
80# This is the common part of all awk programs that read $src
81# This parses the input for one function into the arrays:
82#	argdir, argtype, argname, willrele
83# and calls "doit()" to generate output for the function.
84#
85# Input to this parser is pre-processed slightly by sed
86# so this awk parser doesn't have to work so hard.  The
87# changes done by the sed pre-processing step are:
88#	insert a space beween * and pointer name
89#	replace semicolons with spaces
90#
91sed_prep='s:\*\([^\*/]\):\* \1:g
92s/;/ /'
93awk_parser='
94# Comment line
95/^#/	{ next; }
96# First line of description
97/^vop_/	{
98	name=$1;
99	argc=0;
100	next;
101}
102# Last line of description
103/^}/	{
104	doit();
105	next;
106}
107# Middle lines of description
108{
109	argdir[argc] = $1; i=2;
110	if ($2 == "WILLRELE") {
111		willrele[argc] = 1;
112		i++;
113	} else if ($2 == "WILLUNLOCK") {
114		willrele[argc] = 2;
115		i++;
116	} else if ($2 == "WILLPUT") {
117		willrele[argc] = 3;
118		i++;
119	} else
120		willrele[argc] = 0;
121	argtype[argc] = $i; i++;
122	while (i < NF) {
123		argtype[argc] = argtype[argc]" "$i;
124		i++;
125	}
126	argname[argc] = $i;
127	argc++;
128	next;
129}
130'
131
132# This is put before the copyright on each generated file.
133warning="\
134/*	@NetBSD@	*/
135
136/*
137 * Warning: This file is generated automatically.
138 * (Modifications made here may easily be lost!)
139 *
140 * Created from the file:
141 *	${SRC_ID}
142 * by the script:
143 *	${SCRIPT_ID}
144 */
145"
146
147# This is to satisfy McKusick (get rid of evil spaces 8^)
148anal_retentive='s:\([^/]\*\) :\1:g'
149
150#
151# Redirect stdout to the H file.
152#
153echo "$0: Creating $out_h" 1>&2
154exec > $out_h
155
156# Begin stuff
157echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g'
158echo ""
159echo -n "$copyright"
160echo ''
161echo '#ifndef _SYS_VNODE_IF_H_'
162echo '#define _SYS_VNODE_IF_H_'
163echo ''
164echo '#ifdef _KERNEL'
165echo '#if defined(_LKM) || defined(LKM)'
166echo '/* LKMs always use non-inlined vnode ops. */'
167echo '#define	VNODE_OP_NOINLINE'
168echo '#else'
169echo '#include "opt_vnode_op_noinline.h"'
170echo '#endif'
171echo '#endif /* _KERNEL */'
172echo '
173extern const struct vnodeop_desc vop_default_desc;
174'
175
176# Body stuff
177# This awk program needs toupper() so define it if necessary.
178sed -e "$sed_prep" $src | $awk "$toupper"'
179function doit() {
180	# Declare arg struct, descriptor.
181	printf("\nstruct %s_args {\n", name);
182	printf("\tconst struct vnodeop_desc * a_desc;\n");
183	for (i=0; i<argc; i++) {
184		printf("\t%s a_%s;\n", argtype[i], argname[i]);
185	}
186	printf("};\n");
187	printf("extern const struct vnodeop_desc %s_desc;\n", name);
188	# Prototype it.
189	printf("#ifndef VNODE_OP_NOINLINE\n");
190	printf("static __inline\n");
191	printf("#endif\n");
192	protoarg = sprintf("int %s(", toupper(name));
193	protolen = length(protoarg);
194	printf("%s", protoarg);
195	for (i=0; i<argc; i++) {
196		protoarg = sprintf("%s", argtype[i]);
197		if (i < (argc-1)) protoarg = (protoarg ", ");
198		arglen = length(protoarg);
199		if ((protolen + arglen) > 77) {
200			protoarg = ("\n    " protoarg);
201			arglen += 4;
202			protolen = 0;
203		}
204		printf("%s", protoarg);
205		protolen += arglen;
206	}
207	printf(")\n");
208	printf("#ifndef VNODE_OP_NOINLINE\n");
209	printf("__attribute__((__unused__))\n");
210	printf("#endif\n");
211	printf(";\n");
212	# Define inline function.
213	printf("#ifndef VNODE_OP_NOINLINE\n");
214	printf("static __inline int %s(", toupper(name));
215	for (i=0; i<argc; i++) {
216		printf("%s", argname[i]);
217		if (i < (argc-1)) printf(", ");
218	}
219	printf(")\n");
220	for (i=0; i<argc; i++) {
221		printf("\t%s %s;\n", argtype[i], argname[i]);
222	}
223	printf("{\n\tstruct %s_args a;\n", name);
224	printf("\ta.a_desc = VDESC(%s);\n", name);
225	for (i=0; i<argc; i++) {
226		printf("\ta.a_%s = %s;\n", argname[i], argname[i]);
227	}
228	printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n",
229		argname[0], arg0special, name);
230	printf("#endif\n");
231	vops++;
232}
233BEGIN	{
234	arg0special="";
235	vops = 1; # start at 1, to count the 'default' op
236}
237END	{
238	printf("\n/* Special cases: */\n#include <sys/buf.h>\n");
239	argc=1;
240	argtype[0]="struct buf *";
241	argname[0]="bp";
242	arg0special="->b_vp";
243	name="vop_strategy";
244	doit();
245	name="vop_bwrite";
246	doit();
247
248	printf("\n#define VNODE_OPS_COUNT\t%d\n", vops);
249}
250'"$awk_parser" | sed -e "$anal_retentive"
251
252# End stuff
253echo '
254/* End of special cases. */'
255echo ''
256echo '#endif /* !_SYS_VNODE_IF_H_ */'
257
258#
259# Redirect stdout to the C file.
260#
261echo "$0: Creating $out_c" 1>&2
262exec > $out_c
263
264# Begin stuff
265echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g'
266echo ""
267echo -n "$copyright"
268echo "
269#include <sys/cdefs.h>
270__KERNEL_RCSID(0, \"\$NetBSD\$\");
271"
272
273echo '
274/*
275 * If we have LKM support, always include the non-inline versions for
276 * LKMs.  Otherwise, do it based on the option.
277 */
278#ifdef LKM
279#define	VNODE_OP_NOINLINE
280#else
281#include "opt_vnode_op_noinline.h"
282#endif'
283echo '
284#include <sys/param.h>
285#include <sys/mount.h>
286#include <sys/buf.h>
287#include <sys/vnode.h>
288
289const struct vnodeop_desc vop_default_desc = {
290	0,
291	"default",
292	0,
293	NULL,
294	VDESC_NO_OFFSET,
295	VDESC_NO_OFFSET,
296	VDESC_NO_OFFSET,
297	VDESC_NO_OFFSET,
298	NULL,
299};
300'
301
302# Body stuff
303sed -e "$sed_prep" $src | $awk '
304function do_offset(typematch) {
305	for (i=0; i<argc; i++) {
306		if (argtype[i] == typematch) {
307			printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n",
308				name, argname[i]);
309			return i;
310		};
311	};
312	print "\tVDESC_NO_OFFSET,";
313	return -1;
314}
315
316function doit() {
317	# Define offsets array
318	printf("\nconst int %s_vp_offsets[] = {\n", name);
319	for (i=0; i<argc; i++) {
320		if (argtype[i] == "struct vnode *") {
321			printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
322				name, argname[i]);
323		}
324	}
325	print "\tVDESC_NO_OFFSET";
326	print "};";
327	# Define F_desc
328	printf("const struct vnodeop_desc %s_desc = {\n", name);
329	# offset
330	printf ("\t%d,\n", vop_offset++);
331	# printable name
332	printf ("\t\"%s\",\n", name);
333	# flags
334	printf("\t0");
335	vpnum = 0;
336	for (i=0; i<argc; i++) {
337		if (willrele[i]) {
338			if (willrele[i] == 2) {
339				word = "UNLOCK";
340			} else if (willrele[i] == 3) {
341				word = "PUT";
342			} else {
343				word = "RELE";
344			}
345			if (argdir[i] ~ /OUT/) {
346				printf(" | VDESC_VPP_WILL%s", word);
347			} else {
348				printf(" | VDESC_VP%s_WILL%s", vpnum, word);
349			};
350			vpnum++;
351		}
352	}
353	print ",";
354	# vp offsets
355	printf ("\t%s_vp_offsets,\n", name);
356	# vpp (if any)
357	do_offset("struct vnode **");
358	# cred (if any)
359	do_offset("struct ucred *");
360	# proc (if any)
361	do_offset("struct proc *");
362	# componentname
363	do_offset("struct componentname *");
364	# transport layer information
365	printf ("\tNULL,\n};\n");
366
367	# Define function.
368	printf("#ifdef VNODE_OP_NOINLINE\n");
369	printf("int\n%s(", toupper(name));
370	for (i=0; i<argc; i++) {
371		printf("%s", argname[i]);
372		if (i < (argc-1)) printf(", ");
373	}
374	printf(")\n");
375	for (i=0; i<argc; i++) {
376		printf("\t%s %s;\n", argtype[i], argname[i]);
377	}
378	printf("{\n\tstruct %s_args a;\n", name);
379	printf("\ta.a_desc = VDESC(%s);\n", name);
380	for (i=0; i<argc; i++) {
381		printf("\ta.a_%s = %s;\n", argname[i], argname[i]);
382	}
383	printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n",
384		argname[0], arg0special, name);
385	printf("#endif\n");
386}
387BEGIN	{
388	printf("\n/* Special cases: */\n");
389	# start from 1 (vop_default is at 0)
390	vop_offset=1;
391	argc=1;
392	argdir[0]="IN";
393	argtype[0]="struct buf *";
394	argname[0]="bp";
395	arg0special="->b_vp";
396	willrele[0]=0;
397	name="vop_strategy";
398	doit();
399	name="vop_bwrite";
400	doit();
401	printf("\n/* End of special cases */\n");
402
403	arg0special="";
404}
405'"$awk_parser" | sed -e "$anal_retentive"
406
407# End stuff
408echo '
409/* End of special cases. */'
410
411# Add the vfs_op_descs array to the C file.
412# Begin stuff
413echo '
414const struct vnodeop_desc * const vfs_op_descs[] = {
415	&vop_default_desc,	/* MUST BE FIRST */
416	&vop_strategy_desc,	/* XXX: SPECIAL CASE */
417	&vop_bwrite_desc,	/* XXX: SPECIAL CASE */
418'
419
420# Body stuff
421sed -e "$sed_prep" $src | $awk '
422function doit() {
423	printf("\t&%s_desc,\n", name);
424}
425'"$awk_parser"
426
427# End stuff
428echo '	NULL
429};
430'
431
432exit 0
433
434# Local Variables:
435# tab-width: 4
436# End:
437