xref: /freebsd-14.2/sys/tools/vnode_if.awk (revision 9b50d902)
1#!/bin/sh -
2#
3# Copyright (c) 1992, 1993
4#	The Regents of the University of California.  All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14# 3. All advertising materials mentioning features or use of this software
15#    must display the following acknowledgement:
16#	This product includes software developed by the University of
17#	California, Berkeley and its contributors.
18# 4. Neither the name of the University nor the names of its contributors
19#    may be used to endorse or promote products derived from this software
20#    without specific prior written permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32# SUCH DAMAGE.
33#
34#	@(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
35#
36
37# Script to produce VFS front-end sugar.
38#
39# usage: vnode_if.sh srcfile
40#	(where srcfile is currently /sys/kern/vnode_if.src)
41#
42# These awk scripts are not particularly well written, specifically they
43# don't use arrays well and figure out the same information repeatedly.
44# Please rewrite them if you actually understand how to use awk.  Note,
45# they use nawk extensions and gawk's toupper.
46
47if [ $# -ne 1 ] ; then
48	echo 'usage: vnode_if.sh srcfile'
49	exit 1
50fi
51
52# Name of the source file.
53SRC=$1
54
55# Names of the created files.
56CFILE=vnode_if.c
57HEADER=vnode_if.h
58
59# Awk program (must support nawk extensions and gawk's "toupper")
60# Use "awk" at Berkeley, "gawk" elsewhere.
61AWK=awk
62
63# Print out header information for vnode_if.h.
64cat << END_OF_LEADING_COMMENT > $HEADER
65/*
66 * This file is produced automatically.
67 * Do not modify anything in here by hand.
68 *
69 * Created from @(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
70 */
71
72extern struct vnodeop_desc vop_default_desc;
73END_OF_LEADING_COMMENT
74
75# Awk script to take vnode_if.src and turn it into vnode_if.h.
76$AWK '
77	NF == 0 || $0 ~ "^#" {
78		next;
79	}
80	{
81		# Get the function name.
82		name = $1;
83		uname = toupper(name);
84
85		# Get the function arguments.
86		for (c1 = 0;; ++c1) {
87			if (getline <= 0)
88				exit
89			if ($0 ~ "^};")
90				break;
91			a[c1] = $0;
92		}
93
94		# Print out the vop_F_args structure.
95		printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n",
96		    name);
97		for (c2 = 0; c2 < c1; ++c2) {
98			c3 = split(a[c2], t);
99			printf("\t");
100			if (t[2] ~ "WILLRELE")
101				c4 = 3;
102			else
103				c4 = 2;
104			for (; c4 < c3; ++c4)
105				printf("%s ", t[c4]);
106			beg = match(t[c3], "[^*]");
107			printf("%sa_%s\n",
108			    substr(t[c4], 0, beg - 1), substr(t[c4], beg));
109		}
110		printf("};\n");
111
112		# Print out extern declaration.
113		printf("extern struct vnodeop_desc %s_desc;\n", name);
114
115		# Print out inline struct.
116		printf("static inline int %s(", uname);
117		sep = ", ";
118		for (c2 = 0; c2 < c1; ++c2) {
119			if (c2 == c1 - 1)
120				sep = ")\n";
121			c3 = split(a[c2], t);
122			beg = match(t[c3], "[^*]");
123			end = match(t[c3], ";");
124			printf("%s%s", substr(t[c3], beg, end - beg), sep);
125		}
126		for (c2 = 0; c2 < c1; ++c2) {
127			c3 = split(a[c2], t);
128			printf("\t");
129			if (t[2] ~ "WILLRELE")
130				c4 = 3;
131			else
132				c4 = 2;
133			for (; c4 < c3; ++c4)
134				printf("%s ", t[c4]);
135			beg = match(t[c3], "[^*]");
136			printf("%s%s\n",
137			    substr(t[c4], 0, beg - 1), substr(t[c4], beg));
138		}
139		printf("{\n\tstruct %s_args a;\n\n", name);
140		printf("\ta.a_desc = VDESC(%s);\n", name);
141		for (c2 = 0; c2 < c1; ++c2) {
142			c3 = split(a[c2], t);
143			printf("\t");
144			beg = match(t[c3], "[^*]");
145			end = match(t[c3], ";");
146			printf("a.a_%s = %s\n",
147			    substr(t[c3], beg, end - beg), substr(t[c3], beg));
148		}
149		c1 = split(a[0], t);
150		beg = match(t[c1], "[^*]");
151		end = match(t[c1], ";");
152		printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n",
153		    substr(t[c1], beg, end - beg), name);
154	}' < $SRC >> $HEADER
155
156# Print out header information for vnode_if.c.
157cat << END_OF_LEADING_COMMENT > $CFILE
158/*
159 * This file is produced automatically.
160 * Do not modify anything in here by hand.
161 *
162 * Created from @(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
163 */
164
165#include <sys/param.h>
166#include <sys/mount.h>
167#include <sys/vnode.h>
168
169struct vnodeop_desc vop_default_desc = {
170	0,
171	"default",
172	0,
173	NULL,
174	VDESC_NO_OFFSET,
175	VDESC_NO_OFFSET,
176	VDESC_NO_OFFSET,
177	VDESC_NO_OFFSET,
178	NULL,
179};
180
181END_OF_LEADING_COMMENT
182
183# Awk script to take vnode_if.src and turn it into vnode_if.c.
184$AWK 'function kill_surrounding_ws (s) {
185		sub (/^[ \t]*/, "", s);
186		sub (/[ \t]*$/, "", s);
187		return s;
188	}
189
190	function read_args() {
191		numargs = 0;
192		while (getline ln) {
193			if (ln ~ /}/) {
194				break;
195			};
196
197			# Delete comments, if any.
198			gsub (/\/\*.*\*\//, "", ln);
199
200			# Delete leading/trailing space.
201			ln = kill_surrounding_ws(ln);
202
203			# Pick off direction.
204			if (1 == sub(/^INOUT[ \t]+/, "", ln))
205				dir = "INOUT";
206			else if (1 == sub(/^IN[ \t]+/, "", ln))
207				dir = "IN";
208			else if (1 == sub(/^OUT[ \t]+/, "", ln))
209				dir = "OUT";
210			else
211				bail("No IN/OUT direction for \"" ln "\".");
212
213			# check for "WILLRELE"
214			if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) {
215				rele = "WILLRELE";
216			} else {
217				rele = "WONTRELE";
218			};
219
220			# kill trailing ;
221			if (1 != sub (/;$/, "", ln)) {
222				bail("Missing end-of-line ; in \"" ln "\".");
223			};
224
225			# pick off variable name
226			if (!(i = match(ln, /[A-Za-z0-9_]+$/))) {
227				bail("Missing var name \"a_foo\" in \"" ln "\".");
228			};
229			arg = substr (ln, i);
230			# Want to <<substr(ln, i) = "";>>, but nawk cannot.
231			# Hack around this.
232			ln = substr(ln, 1, i-1);
233
234			# what is left must be type
235			# (put clean it up some)
236			type = ln;
237			gsub (/[ \t]+/, " ", type);   # condense whitespace
238			type = kill_surrounding_ws(type);
239
240			# (boy this was easier in Perl)
241
242			numargs++;
243			dirs[numargs] = dir;
244			reles[numargs] = rele;
245			types[numargs] = type;
246			args[numargs] = arg;
247		};
248	}
249
250	function generate_operation_vp_offsets() {
251		printf ("int %s_vp_offsets[] = {\n", name);
252		# as a side effect, figure out the releflags
253		releflags = "";
254		vpnum = 0;
255		for (i=1; i<=numargs; i++) {
256			if (types[i] == "struct vnode *") {
257				printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
258					name, args[i]);
259				if (reles[i] == "WILLRELE") {
260					releflags = releflags "|VDESC_VP" vpnum "_WILLRELE";
261				};
262				vpnum++;
263			};
264		};
265		sub (/^\|/, "", releflags);
266		print "\tVDESC_NO_OFFSET";
267		print "};";
268	}
269
270	function find_arg_with_type (type) {
271		for (i=1; i<=numargs; i++) {
272			if (types[i] == type) {
273				return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")";
274			};
275		};
276		return "VDESC_NO_OFFSET";
277	}
278
279	function generate_operation_desc() {
280		printf ("struct vnodeop_desc %s_desc = {\n", name);
281		# offset
282		printf ("\t0,\n");
283		# printable name
284		printf ("\t\"%s\",\n", name);
285		# flags
286		vppwillrele = "";
287		for (i=1; i<=numargs; i++) {
288			if (types[i] == "struct vnode **" &&
289				(reles[i] == "WILLRELE")) {
290				vppwillrele = "|VDESC_VPP_WILLRELE";
291			};
292		};
293		if (releflags == "") {
294			printf ("\t0%s,\n", vppwillrele);
295		} else {
296			printf ("\t%s%s,\n", releflags, vppwillrele);
297		};
298		# vp offsets
299		printf ("\t%s_vp_offsets,\n", name);
300		# vpp (if any)
301		printf ("\t%s,\n", find_arg_with_type("struct vnode **"));
302		# cred (if any)
303		printf ("\t%s,\n", find_arg_with_type("struct ucred *"));
304		# proc (if any)
305		printf ("\t%s,\n", find_arg_with_type("struct proc *"));
306		# componentname
307		printf ("\t%s,\n", find_arg_with_type("struct componentname *"));
308		# transport layer information
309		printf ("\tNULL,\n};\n");
310	}
311
312	NF == 0 || $0 ~ "^#" {
313		next;
314	}
315	{
316		# get the function name
317		name = $1;
318
319		# get the function arguments
320		read_args();
321
322		# Print out the vop_F_vp_offsets structure.  This all depends
323		# on naming conventions and nothing else.
324		generate_operation_vp_offsets();
325
326		# Print out the vnodeop_desc structure.
327		generate_operation_desc();
328
329		printf "\n";
330
331	}' < $SRC >> $CFILE
332# THINGS THAT DON'T WORK RIGHT YET.
333#
334# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as
335# arguments.  This means that these operations can't function successfully
336# through a bypass routine.
337#
338# Bwrite and strategy will be replaced when the VM page/buffer cache
339# integration happens.
340#
341# To get around this problem for now we handle these ops as special cases.
342
343cat << END_OF_SPECIAL_CASES >> $HEADER
344#include <sys/buf.h>
345struct vop_strategy_args {
346	struct vnodeop_desc *a_desc;
347	struct buf *a_bp;
348};
349extern struct vnodeop_desc vop_strategy_desc;
350static inline int VOP_STRATEGY(bp)
351	struct buf *bp;
352{
353	struct vop_strategy_args a;
354
355	a.a_desc = VDESC(vop_strategy);
356	a.a_bp = bp;
357	return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a));
358}
359
360struct vop_bwrite_args {
361	struct vnodeop_desc *a_desc;
362	struct buf *a_bp;
363};
364extern struct vnodeop_desc vop_bwrite_desc;
365static inline int VOP_BWRITE(bp)
366	struct buf *bp;
367{
368	struct vop_bwrite_args a;
369
370	a.a_desc = VDESC(vop_bwrite);
371	a.a_bp = bp;
372	return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a));
373}
374END_OF_SPECIAL_CASES
375
376cat << END_OF_SPECIAL_CASES >> $CFILE
377int vop_strategy_vp_offsets[] = {
378	VDESC_NO_OFFSET
379};
380struct vnodeop_desc vop_strategy_desc = {
381	0,
382	"vop_strategy",
383	0,
384	vop_strategy_vp_offsets,
385	VDESC_NO_OFFSET,
386	VDESC_NO_OFFSET,
387	VDESC_NO_OFFSET,
388	VDESC_NO_OFFSET,
389	NULL,
390};
391int vop_bwrite_vp_offsets[] = {
392	VDESC_NO_OFFSET
393};
394struct vnodeop_desc vop_bwrite_desc = {
395	0,
396	"vop_bwrite",
397	0,
398	vop_bwrite_vp_offsets,
399	VDESC_NO_OFFSET,
400	VDESC_NO_OFFSET,
401	VDESC_NO_OFFSET,
402	VDESC_NO_OFFSET,
403	NULL,
404};
405END_OF_SPECIAL_CASES
406
407# Add the vfs_op_descs array to the C file.
408$AWK '
409	BEGIN {
410		printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
411		printf("\t&vop_default_desc,	/* MUST BE FIRST */\n");
412		printf("\t&vop_strategy_desc,	/* XXX: SPECIAL CASE */\n");
413		printf("\t&vop_bwrite_desc,	/* XXX: SPECIAL CASE */\n");
414	}
415	END {
416		printf("\tNULL\n};\n");
417	}
418	NF == 0 || $0 ~ "^#" {
419		next;
420	}
421	{
422		# Get the function name.
423		printf("\t&%s_desc,\n", $1);
424
425		# Skip the function arguments.
426		for (;;) {
427			if (getline <= 0)
428				exit
429			if ($0 ~ "^};")
430				break;
431		}
432	}' < $SRC >> $CFILE
433
434