Module Name:    src
Committed By:   thorpej
Date:           Wed Sep 15 17:25:14 UTC 2021

Added Files:
        src/sys/kern: gendevcalls.awk

Log Message:
Add an awk program that reads in a device call interface description
file and emits a header file containing the argument and call binding
structures for those calls.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/kern/gendevcalls.awk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sys/kern/gendevcalls.awk
diff -u /dev/null src/sys/kern/gendevcalls.awk:1.1
--- /dev/null	Wed Sep 15 17:25:14 2021
+++ src/sys/kern/gendevcalls.awk	Wed Sep 15 17:25:14 2021
@@ -0,0 +1,208 @@
+#! /usr/bin/awk -f
+#	$NetBSD: gendevcalls.awk,v 1.1 2021/09/15 17:25:14 thorpej Exp $
+#
+# Copyright (c) 2021 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Jason R. Thorpe.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# Parses a device call definition file and produces argument and
+# binding structures.
+#
+
+function emit_binding(field) {
+	printf("union %s_binding {\n", call_name_ub)
+	printf("\tstruct device_call_generic generic;\n")
+	if (field != "") {
+		printf("\tstruct {\n")
+		printf("\t\tconst char *name;\n")
+		printf("\t\tstruct %s_args *args;\n", call_name_ub)
+		printf("\t} %s;\n", field);
+	}
+	printf("};\n")
+}
+
+function emit_name_macro() {
+	printf("\n")
+	printf("#define %s_STR \"%s\"\n", call_name_ub_uc, call_name)
+}
+
+function emit_invoke_macro(field, marg, carg) {
+	printf("\n")
+	printf("#define %s%s \\\n", call_name_ub_uc, marg)
+	printf("\t&((const union %s_binding){ \\\n", call_name_ub)
+	printf("\t\t.%s.name = \"%s\", \\\n", field, call_name)
+	printf("\t\t.%s.args = %s, \\\n", field, carg)
+	printf("\t})\n")
+}
+
+function start_decl(arg) {
+	if (state == "expecting-subsystem") {
+		print "must declare a subsystem before declaring a call " \
+		    "at line " NR \
+		    > "/dev/stderr"
+		exit 1
+	}
+
+	if (state != "expecting-decl-start") {
+		print "unexpected start of declaration at line " NR \
+		    > "/dev/stderr"
+		exit 1
+	}
+
+	call_name = arg
+
+	if (index(call_name, call_name_prefix) != 1) {
+		printf("method name '%s' at line %d must begin with '%s'\n", \
+		    call_name, NR, call_name_prefix) \
+		    > "/dev/stderr"
+		exit 1
+	}
+
+	call_name_ub = arg
+	gsub("\-", "_", call_name_ub)
+	call_name_ub_uc = toupper(call_name_ub)
+}
+
+NR == 1 {
+	VERSION = $0
+	gsub("\\$", "", VERSION)
+	gsub(/ $/, "", VERSION)
+
+	printf("/*\t$NetBSD" "$\t*/\n\n")
+	printf("/*\n")
+	printf(" * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.\n")
+	printf(" *\n")
+	printf(" * generated from:\n")
+	printf(" *\t%s\n", VERSION)
+	printf(" */\n")
+
+	subsystem = ""
+	state = "expecting-subsystem"
+
+	next
+}
+#
+# Subystem declaration.  We use this to generate header file guards,
+# as well as to sanity-check the method names when they are declared.
+#
+state == "expecting-subsystem" && \
+/^subsystem[ \t]+[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]*;[ \t]*$/ {
+	subsystem = $2
+
+	# strip the trailing ;
+	gsub(";$", "", subsystem)
+
+	subsystem_ub = subsystem
+	gsub("\-", "_", subsystem_ub)
+	subsystem_ub_uc = toupper(subsystem_ub)
+
+	# now tack on a trailing - for sanity checking method
+	# names later.
+	call_name_prefix = subsystem "-"
+
+	# Emit the leading header guard.
+	printf("#ifndef _%s_CALLS_H_\n", subsystem_ub_uc)
+	printf("#define _%s_CALLS_H_\n", subsystem_ub_uc)
+
+	# Pull in <sys/device.h> for 'struct device_call_generic'.
+	printf("\n#include <sys/device.h>\n")
+
+	state = "expecting-decl-start"
+
+	next
+}
+#
+# Beginning of a call-with-arguments declaration.  Gather up the various
+# forms of the method name and emit the beginning of the structure declaration.
+#
+/^[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]+{[ \t]*$/ {
+	start_decl($1)
+
+	# Emit the args structure declaration.
+	printf("struct %s_args {\n", call_name_ub)
+
+	state = "expecting-decl-end"
+
+	next
+}
+#
+# A call-without-arguments declaration.
+#
+/^[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]*;[ \t]*$/ {
+	# strip the trailing ;
+	call_name = $1
+	gsub(";$", "", call_name)
+
+	start_decl(call_name)
+
+	emit_binding("")
+	emit_name_macro()
+	emit_invoke_macro("generic", "", "NULL")
+
+	next
+}
+#
+# End of a declaration.  Wrap up the structure declaration and emit
+# the binding information.
+#
+/^}[ \t]*;[ \t]*$/ {
+	if (state != "expecting-decl-end") {
+		print "unexpected end of declaration at line " NR \
+		    > "/dev/stderr"
+		exit 1
+	}
+
+	# Terminate the args structure declaration.
+	printf("};\n")
+
+	printf("\n")
+	emit_binding("binding")
+	emit_name_macro()
+	emit_invoke_macro("binding", "(_args_)", "(_args_)")
+
+	state = "expecting-decl-start"
+
+	next
+}
+#
+# Default action is to simply emit the line as it exists in the source
+# file.
+#
+{
+	print $0
+}
+END {
+	if (state != "expecting-decl-start") {
+		print "unexpected end of file at line " NR \
+		    > "/dev/stderr"
+		exit 1
+	}
+
+	# Emit the trailing header guard.
+	printf("\n#endif /* _%s_CALLS_H_ */\n", subsystem_ub_uc)
+}

Reply via email to