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