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) +}