put redundant stuff in subroutines; add WILLRELE support
[unix-history] / usr / src / sys / kern / vnode_if.sh
index c444a4a..0458855 100644 (file)
@@ -5,37 +5,58 @@
 #
 # %sccs.include.redist.sh%
 #
 #
 # %sccs.include.redist.sh%
 #
-#      @(#)vnode_if.sh 7.1 (Berkeley) %G%
+#      @(#)vnode_if.sh 7.4 (Berkeley) %G%
 #
 
 # Script to produce VFS front-end sugar.
 #
 
 # Script to produce VFS front-end sugar.
+#
+# usage: vnode_if.sh srcfile
+#      (where srcfile is currently /sys/kern/vnode_if.src)
+#
+# These awk scripts are not particularly well written, specifically they
+# don't use arrays well and figure out the same information repeatedly.
+# Please rewrite them if you actually understand how to use awk.  Note,
+# they use nawk extensions and gawk's toupper.
+
+if [ $# -ne 1 ] ; then
+       echo 'usage: vnode_if.sh srcfile'
+       exit 1
+fi
+
+# Name of the source file.
+SRC=$1
 
 
-cat << END_OF_LEADING_COMMENT
+# Names of the created files.
+CFILE=vnode_if.c
+HEADER=vnode_if.h
+
+# Awk program (must support nawk extensions and gawk's "toupper")
+# Use "awk" at Berkeley, "gawk" elsewhere.
+AWK=awk
+
+# Print out header information for vnode_if.h.
+cat << END_OF_LEADING_COMMENT > $HEADER
 /*
 /*
- * This file is produced by the script /sys/kern/vnode_if.sh.
+ * This file is produced automatically.
  * Do not modify anything in here by hand.
  *
  * Do not modify anything in here by hand.
  *
- *     @(#)vnode_if.sh 7.1 (Berkeley) %G%
+ * Created from @(#)vnode_if.sh        7.4 (Berkeley) %G%
  */
  */
+
 extern struct vnodeop_desc vop_default_desc;
 END_OF_LEADING_COMMENT
 
 # Awk script to take vnode_if.src and turn it into vnode_if.h.
 extern struct vnodeop_desc vop_default_desc;
 END_OF_LEADING_COMMENT
 
 # Awk script to take vnode_if.src and turn it into vnode_if.h.
-#
-# This script is not particularly well written, it figures out the
-# same stuff repeatedly.  Feel free to fix it.  Note, it uses nawk
-# extensions.
-
-awk '
+$AWK '
        NF == 0 || $0 ~ "^#" {
                next;
        }
        {
        NF == 0 || $0 ~ "^#" {
                next;
        }
        {
-               # get the function name
+               # Get the function name.
                name = $1;
                uname = toupper(name);
 
                name = $1;
                uname = toupper(name);
 
-               # get the function arguments
+               # Get the function arguments.
                for (c1 = 0;; ++c1) {
                        if (getline <= 0)
                                exit
                for (c1 = 0;; ++c1) {
                        if (getline <= 0)
                                exit
@@ -44,13 +65,17 @@ awk '
                        a[c1] = $0;
                }
 
                        a[c1] = $0;
                }
 
-               # print out the vop_F_args structure
+               # Print out the vop_F_args structure.
                printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n",
                    name);
                for (c2 = 0; c2 < c1; ++c2) {
                        c3 = split(a[c2], t);
                        printf("\t");
                printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n",
                    name);
                for (c2 = 0; c2 < c1; ++c2) {
                        c3 = split(a[c2], t);
                        printf("\t");
-                       for (c4 = 2; c4 < c3; ++c4)
+                       if (t[2] ~ "WILLRELE")
+                               c4 = 3;
+                       else 
+                               c4 = 2;
+                       for (; c4 < c3; ++c4)
                                printf("%s ", t[c4]);
                        beg = match(t[c3], "[^*]");
                        printf("%sa_%s\n",
                                printf("%s ", t[c4]);
                        beg = match(t[c3], "[^*]");
                        printf("%sa_%s\n",
@@ -58,10 +83,10 @@ awk '
                }
                printf("};\n");
 
                }
                printf("};\n");
 
-               # print out extern declaration
+               # Print out extern declaration.
                printf("extern struct vnodeop_desc %s_desc;\n", name);
 
                printf("extern struct vnodeop_desc %s_desc;\n", name);
 
-               # print out inline struct
+               # Print out inline struct.
                printf("static inline int %s(", uname);
                sep = ", ";
                for (c2 = 0; c2 < c1; ++c2) {
                printf("static inline int %s(", uname);
                sep = ", ";
                for (c2 = 0; c2 < c1; ++c2) {
@@ -75,7 +100,11 @@ awk '
                for (c2 = 0; c2 < c1; ++c2) {
                        c3 = split(a[c2], t);
                        printf("\t");
                for (c2 = 0; c2 < c1; ++c2) {
                        c3 = split(a[c2], t);
                        printf("\t");
-                       for (c4 = 2; c4 < c3; ++c4)
+                       if (t[2] ~ "WILLRELE")
+                               c4 = 3;
+                       else
+                               c4 = 2;
+                       for (; c4 < c3; ++c4)
                                printf("%s ", t[c4]);
                        beg = match(t[c3], "[^*]");
                        printf("%s%s\n",
                                printf("%s ", t[c4]);
                        beg = match(t[c3], "[^*]");
                        printf("%s%s\n",
@@ -96,8 +125,184 @@ awk '
                end = match(t[c1], ";");
                printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n",
                    substr(t[c1], beg, end - beg), name);
                end = match(t[c1], ";");
                printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n",
                    substr(t[c1], beg, end - beg), name);
-       }'
+       }' < $SRC >> $HEADER
+
+# Print out header information for vnode_if.c.
+cat << END_OF_LEADING_COMMENT > $CFILE
+/*
+ * This file is produced automatically.
+ * Do not modify anything in here by hand.
+ *
+ * Created from @(#)vnode_if.sh        7.4 (Berkeley) %G%
+ */
 
 
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+
+struct vnodeop_desc vop_default_desc = {
+       0,
+       "default",
+       0,
+       NULL,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       NULL,
+};
+
+END_OF_LEADING_COMMENT
+
+# Awk script to take vnode_if.src and turn it into vnode_if.c.
+$AWK 'function kill_surrounding_ws (s) {
+               sub (/^[ \t]*/, "", s);
+               sub (/[ \t]*$/, "", s);
+               return s;
+       }
+
+       function read_args() {
+               numargs = 0;
+               while (getline ln) {
+                       if (ln ~ /}/) {
+                               break;
+                       };
+       
+                       # Delete comments, if any.
+                       gsub (/\/\*.*\*\//, "", ln);
+                       
+                       # Delete leading/trailing space.
+                       ln = kill_surrounding_ws(ln);
+       
+                       # Pick off direction.
+                       if (1 == sub(/^INOUT[ \t]+/, "", ln))
+                               dir = "INOUT";
+                       else if (1 == sub(/^IN[ \t]+/, "", ln))
+                               dir = "IN";
+                       else if (1 == sub(/^OUT[ \t]+/, "", ln))
+                               dir = "OUT";
+                       else
+                               bail("No IN/OUT direction for \"" ln "\".");
+
+                       # check for "WILLRELE"
+                       if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) {
+                               rele = "WILLRELE";
+                       } else {
+                               rele = "WONTRELE";
+                       };
+       
+                       # kill trailing ;
+                       if (1 != sub (/;$/, "", ln)) {
+                               bail("Missing end-of-line ; in \"" ln "\".");
+                       };
+       
+                       # pick off variable name
+                       if (!(i = match(ln, /[A-Za-z0-9_]+$/))) {
+                               bail("Missing var name \"a_foo\" in \"" ln "\".");
+                       };
+                       arg = substr (ln, i);
+                       # Want to <<substr(ln, i) = "";>>, but nawk cannot.
+                       # Hack around this.
+                       ln = substr(ln, 1, i-1);
+       
+                       # what is left must be type
+                       # (put clean it up some)
+                       type = ln;
+                       gsub (/[ \t]+/, " ", type);   # condense whitespace
+                       type = kill_surrounding_ws(type);
+       
+                       # (boy this was easier in Perl)
+       
+                       numargs++;
+                       dirs[numargs] = dir;
+                       reles[numargs] = rele;
+                       types[numargs] = type;
+                       args[numargs] = arg;
+               };
+       }
+
+       function generate_operation_vp_offsets() {
+               printf ("int %s_vp_offsets[] = {\n", name);
+               # as a side effect, figure out the releflags
+               releflags = "";
+               vpnum = 0;
+               for (i=1; i<=numargs; i++) {
+                       if (types[i] == "struct vnode *") {
+                               printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
+                                       name, args[i]);
+                               if (reles[i] == "WILLRELE") {
+                                       releflags = releflags "|VDESC_VP" vpnum "_WILLRELE";
+                               };
+                               vpnum++;
+                       };
+               };
+               sub (/^\|/, "", releflags);
+               print "\tVDESC_NO_OFFSET";
+               print "};";
+       }
+       
+       function find_arg_with_type (type) {
+               for (i=1; i<=numargs; i++) {
+                       if (types[i] == type) {
+                               return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")";
+                       };
+               };
+               return "VDESC_NO_OFFSET";
+       }
+       
+       function generate_operation_desc() {
+               printf ("struct vnodeop_desc %s_desc = {\n", name);
+               # offset
+               printf ("\t0,\n");
+               # printable name
+               printf ("\t\"%s\",\n", name);
+               # flags
+               vppwillrele = "";
+               for (i=1; i<=numargs; i++) {
+                       if (types[i] == "struct vnode **" &&
+                               (reles[i] == "WILLRELE")) {
+                               vppwillrele = "|VDESC_VPP_WILLRELE";
+                       };
+               };
+               if (releflags == "") {
+                       printf ("\t0%s,\n", vppwillrele);
+               } else {
+                       printf ("\t%s%s,\n", releflags, vppwillrele);
+               };
+               # vp offsets
+               printf ("\t%s_vp_offsets,\n", name);
+               # vpp (if any)
+               printf ("\t%s,\n", find_arg_with_type("struct vnode **"));
+               # cred (if any)
+               printf ("\t%s,\n", find_arg_with_type("struct ucred *"));
+               # proc (if any)
+               printf ("\t%s,\n", find_arg_with_type("struct proc *"));
+               # componentname
+               printf ("\t%s,\n", find_arg_with_type("struct componentname *"));
+               # transport layer information
+               printf ("\tNULL,\n};\n");
+       }
+
+       NF == 0 || $0 ~ "^#" {
+               next;
+       }
+       {
+               # get the function name
+               name = $1;
+
+               # get the function arguments
+               read_args();
+
+               # Print out the vop_F_vp_offsets structure.  This all depends
+               # on naming conventions and nothing else.
+               generate_operation_vp_offsets();
+
+               # Print out the vnodeop_desc structure.
+               generate_operation_desc();
+
+               printf "\n";
+
+       }' < $SRC >> $CFILE
 # THINGS THAT DON'T WORK RIGHT YET.
 # 
 # Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as
 # THINGS THAT DON'T WORK RIGHT YET.
 # 
 # Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as
@@ -109,7 +314,7 @@ awk '
 #
 # To get around this problem for now we handle these ops as special cases.
 
 #
 # To get around this problem for now we handle these ops as special cases.
 
-cat << END_OF_SPECIAL_CASES
+cat << END_OF_SPECIAL_CASES >> $HEADER
 #include <sys/buf.h>
 struct vop_strategy_args {
        struct vnodeop_desc *a_desc;
 #include <sys/buf.h>
 struct vop_strategy_args {
        struct vnodeop_desc *a_desc;
@@ -141,3 +346,62 @@ static inline int VOP_BWRITE(bp)
        return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a));
 }
 END_OF_SPECIAL_CASES
        return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a));
 }
 END_OF_SPECIAL_CASES
+
+cat << END_OF_SPECIAL_CASES >> $CFILE
+int vop_strategy_vp_offsets[] = {
+       VDESC_NO_OFFSET
+};
+struct vnodeop_desc vop_strategy_desc = {
+       0,
+       "vop_strategy",
+       0,
+       vop_strategy_vp_offsets,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       NULL,
+};
+int vop_bwrite_vp_offsets[] = {
+       VDESC_NO_OFFSET
+};
+struct vnodeop_desc vop_bwrite_desc = {
+       0,
+       "vop_bwrite",
+       0,
+       vop_bwrite_vp_offsets,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
+       NULL,
+};
+END_OF_SPECIAL_CASES
+
+# Add the vfs_op_descs array to the C file.
+$AWK '
+       BEGIN {
+               printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
+               printf("\t&vop_default_desc,    /* MUST BE FIRST */\n");
+               printf("\t&vop_strategy_desc,   /* XXX: SPECIAL CASE */\n");
+               printf("\t&vop_bwrite_desc,     /* XXX: SPECIAL CASE */\n");
+       }
+       END {
+               printf("\tNULL\n};\n");
+       }
+       NF == 0 || $0 ~ "^#" {
+               next;
+       }
+       {
+               # Get the function name.
+               printf("\t&%s_desc,\n", $1);
+
+               # Skip the function arguments.
+               for (;;) {
+                       if (getline <= 0)
+                               exit
+                       if ($0 ~ "^};")
+                               break;
+               }
+       }' < $SRC >> $CFILE
+