put redundant stuff in subroutines; add WILLRELE support
[unix-history] / usr / src / sys / kern / vnode_if.sh
index 286a847..0458855 100644 (file)
@@ -5,7 +5,7 @@
 #
 # %sccs.include.redist.sh%
 #
 #
 # %sccs.include.redist.sh%
 #
-#      @(#)vnode_if.sh 7.2 (Berkeley) %G%
+#      @(#)vnode_if.sh 7.4 (Berkeley) %G%
 #
 
 # Script to produce VFS front-end sugar.
 #
 
 # Script to produce VFS front-end sugar.
 # 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,
 # 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.
+# they use nawk extensions and gawk's toupper.
 
 if [ $# -ne 1 ] ; then
 
 if [ $# -ne 1 ] ; then
-       printf 'usage: vnode_if.sh srcfile\n'
+       echo 'usage: vnode_if.sh srcfile'
        exit 1
 fi
 
        exit 1
 fi
 
@@ -30,20 +30,24 @@ SRC=$1
 CFILE=vnode_if.c
 HEADER=vnode_if.h
 
 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
 /*
 # 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.2 (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.
-awk '
+$AWK '
        NF == 0 || $0 ~ "^#" {
                next;
        }
        NF == 0 || $0 ~ "^#" {
                next;
        }
@@ -67,7 +71,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("%sa_%s\n",
                                printf("%s ", t[c4]);
                        beg = match(t[c3], "[^*]");
                        printf("%sa_%s\n",
@@ -92,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",
@@ -118,10 +130,10 @@ awk '
 # Print out header information for vnode_if.c.
 cat << END_OF_LEADING_COMMENT > $CFILE
 /*
 # Print out header information for vnode_if.c.
 cat << END_OF_LEADING_COMMENT > $CFILE
 /*
- * 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.2 (Berkeley) %G%
+ * Created from @(#)vnode_if.sh        7.4 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -136,13 +148,141 @@ struct vnodeop_desc vop_default_desc = {
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        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.
        NULL,
 };
 
 END_OF_LEADING_COMMENT
 
 # Awk script to take vnode_if.src and turn it into vnode_if.c.
-awk '
+$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;
        }
        NF == 0 || $0 ~ "^#" {
                next;
        }
@@ -151,77 +291,18 @@ awk '
                name = $1;
 
                # get the function arguments
                name = $1;
 
                # get the function arguments
-               for (c1 = 0;; ++c1) {
-                       if (getline <= 0)
-                               exit
-                       if ($0 ~ "^};")
-                               break;
-                       a[c1] = $0;
-               }
+               read_args();
 
                # Print out the vop_F_vp_offsets structure.  This all depends
                # on naming conventions and nothing else.
 
                # Print out the vop_F_vp_offsets structure.  This all depends
                # on naming conventions and nothing else.
-               printf("int %s_vp_offsets[] = {\n", name);
-               for (c2 = 0; c2 < c1; ++c2) {
-                       c3 = split(a[c2], t);
-                       if (c3 != 4 || t[1] !~ /^IN$/ || t[2] !~ /^struct$/ ||
-                           t[3] !~ /^vnode$/ || t[4] !~ /.*vp;$/)
-                               continue;
-                       beg = match(t[c3], "[^*]");
-                       end = match(t[c3], ";");
-                       printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n",
-                           name, substr(t[4], beg, end - beg));
-               }
-               printf("\tVDESC_NO_OFFSET\n};\n");
+               generate_operation_vp_offsets();
 
                # Print out the vnodeop_desc structure.
 
                # Print out the vnodeop_desc structure.
-               printf("struct vnodeop_desc %s_desc = {\n", name);
-               printf("\t0,\n\t\"%s\",\n\t0,\n\t%s_vp_offsets,\n", name, name);
+               generate_operation_desc();
 
 
-               # Print out return vpp entry, if any.
-               for (found = c2 = 0; c2 < c1; ++c2) {
-                       c3 = split(a[c2], t);
-                       if (c3 != 4 || t[1] !~ /^OUT$/ || t[2] !~ /^struct$/ ||
-                           t[3] !~ /^vnode$/)
-                               continue;
-                       printf("\tVOPARG_OFFSETOF(struct %s_args, a_vpp),\n",
-                           name);
-                       found = 1;
-                       break;
-               }
-               if (found == 0)
-                       printf("\tVDESC_NO_OFFSET,\n");
+               printf "\n";
 
 
-               # Print out cred entry, if any.
-               for (found = c2 = 0; c2 < c1; ++c2) {
-                       c3 = split(a[c2], t);
-                       if (c3 != 4 || t[1] !~ /^IN$/ || t[2] !~ /^struct$/ ||
-                           t[3] !~ /^ucred$/)
-                               continue;
-                       printf("\tVOPARG_OFFSETOF(struct %s_args, a_cred),\n",
-                           name);
-                       found = 1;
-                       break;
-               }
-               if (found == 0)
-                       printf("\tVDESC_NO_OFFSET,\n");
-
-               # Print out proc entry, if any.
-               for (found = c2 = 0; c2 < c1; ++c2) {
-                       c3 = split(a[c2], t);
-                       if (c3 != 4 || t[1] !~ /^IN$/ || t[2] !~ /^struct$/ ||
-                           t[3] !~ /^proc$/)
-                               continue;
-                       printf("\tVOPARG_OFFSETOF(struct %s_args, a_p),\n",
-                           name);
-                       found = 1;
-                       break;
-               }
-               if (found == 0)
-                       printf("\tVDESC_NO_OFFSET,\n");
-               printf("\tNULL,\n};\n");
        }' < $SRC >> $CFILE
        }' < $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
@@ -278,6 +359,7 @@ struct vnodeop_desc vop_strategy_desc = {
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
+       VDESC_NO_OFFSET,
        NULL,
 };
 int vop_bwrite_vp_offsets[] = {
        NULL,
 };
 int vop_bwrite_vp_offsets[] = {
@@ -291,14 +373,15 @@ struct vnodeop_desc vop_bwrite_desc = {
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        VDESC_NO_OFFSET,
        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.
        NULL,
 };
 END_OF_SPECIAL_CASES
 
 # Add the vfs_op_descs array to the C file.
-awk '
+$AWK '
        BEGIN {
        BEGIN {
-               printf("struct vnodeop_desc *vfs_op_descs[] = {\n");
+               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");
                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");
@@ -321,3 +404,4 @@ awk '
                                break;
                }
        }' < $SRC >> $CFILE
                                break;
                }
        }' < $SRC >> $CFILE
+