Home | History | Annotate | Line # | Download | only in kern
      1 #! /usr/bin/awk -f
      2 #	$NetBSD: gendevcalls.awk,v 1.2 2024/02/09 22:08:37 andvar Exp $
      3 #
      4 # Copyright (c) 2021 The NetBSD Foundation, Inc.
      5 # All rights reserved.
      6 #
      7 # This code is derived from software contributed to The NetBSD Foundation
      8 # by Jason R. Thorpe.
      9 #
     10 # Redistribution and use in source and binary forms, with or without
     11 # modification, are permitted provided that the following conditions
     12 # are met:
     13 # 1. Redistributions of source code must retain the above copyright
     14 #    notice, this list of conditions and the following disclaimer.
     15 # 2. Redistributions in binary form must reproduce the above copyright
     16 #    notice, this list of conditions and the following disclaimer in the
     17 #    documentation and/or other materials provided with the distribution.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29 # POSSIBILITY OF SUCH DAMAGE.
     30 #
     31 
     32 #
     33 # Parses a device call definition file and produces argument and
     34 # binding structures.
     35 #
     36 
     37 function emit_binding(field) {
     38 	printf("union %s_binding {\n", call_name_ub)
     39 	printf("\tstruct device_call_generic generic;\n")
     40 	if (field != "") {
     41 		printf("\tstruct {\n")
     42 		printf("\t\tconst char *name;\n")
     43 		printf("\t\tstruct %s_args *args;\n", call_name_ub)
     44 		printf("\t} %s;\n", field);
     45 	}
     46 	printf("};\n")
     47 }
     48 
     49 function emit_name_macro() {
     50 	printf("\n")
     51 	printf("#define %s_STR \"%s\"\n", call_name_ub_uc, call_name)
     52 }
     53 
     54 function emit_invoke_macro(field, marg, carg) {
     55 	printf("\n")
     56 	printf("#define %s%s \\\n", call_name_ub_uc, marg)
     57 	printf("\t&((const union %s_binding){ \\\n", call_name_ub)
     58 	printf("\t\t.%s.name = \"%s\", \\\n", field, call_name)
     59 	printf("\t\t.%s.args = %s, \\\n", field, carg)
     60 	printf("\t})\n")
     61 }
     62 
     63 function start_decl(arg) {
     64 	if (state == "expecting-subsystem") {
     65 		print "must declare a subsystem before declaring a call " \
     66 		    "at line " NR \
     67 		    > "/dev/stderr"
     68 		exit 1
     69 	}
     70 
     71 	if (state != "expecting-decl-start") {
     72 		print "unexpected start of declaration at line " NR \
     73 		    > "/dev/stderr"
     74 		exit 1
     75 	}
     76 
     77 	call_name = arg
     78 
     79 	if (index(call_name, call_name_prefix) != 1) {
     80 		printf("method name '%s' at line %d must begin with '%s'\n", \
     81 		    call_name, NR, call_name_prefix) \
     82 		    > "/dev/stderr"
     83 		exit 1
     84 	}
     85 
     86 	call_name_ub = arg
     87 	gsub("\-", "_", call_name_ub)
     88 	call_name_ub_uc = toupper(call_name_ub)
     89 }
     90 
     91 NR == 1 {
     92 	VERSION = $0
     93 	gsub("\\$", "", VERSION)
     94 	gsub(/ $/, "", VERSION)
     95 
     96 	printf("/*\t$NetBSD" "$\t*/\n\n")
     97 	printf("/*\n")
     98 	printf(" * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.\n")
     99 	printf(" *\n")
    100 	printf(" * generated from:\n")
    101 	printf(" *\t%s\n", VERSION)
    102 	printf(" */\n")
    103 
    104 	subsystem = ""
    105 	state = "expecting-subsystem"
    106 
    107 	next
    108 }
    109 #
    110 # Subsystem declaration.  We use this to generate header file guards,
    111 # as well as to sanity-check the method names when they are declared.
    112 #
    113 state == "expecting-subsystem" && \
    114 /^subsystem[ \t]+[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]*;[ \t]*$/ {
    115 	subsystem = $2
    116 
    117 	# strip the trailing ;
    118 	gsub(";$", "", subsystem)
    119 
    120 	subsystem_ub = subsystem
    121 	gsub("\-", "_", subsystem_ub)
    122 	subsystem_ub_uc = toupper(subsystem_ub)
    123 
    124 	# now tack on a trailing - for sanity checking method
    125 	# names later.
    126 	call_name_prefix = subsystem "-"
    127 
    128 	# Emit the leading header guard.
    129 	printf("#ifndef _%s_CALLS_H_\n", subsystem_ub_uc)
    130 	printf("#define _%s_CALLS_H_\n", subsystem_ub_uc)
    131 
    132 	# Pull in <sys/device.h> for 'struct device_call_generic'.
    133 	printf("\n#include <sys/device.h>\n")
    134 
    135 	state = "expecting-decl-start"
    136 
    137 	next
    138 }
    139 #
    140 # Beginning of a call-with-arguments declaration.  Gather up the various
    141 # forms of the method name and emit the beginning of the structure declaration.
    142 #
    143 /^[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]+{[ \t]*$/ {
    144 	start_decl($1)
    145 
    146 	# Emit the args structure declaration.
    147 	printf("struct %s_args {\n", call_name_ub)
    148 
    149 	state = "expecting-decl-end"
    150 
    151 	next
    152 }
    153 #
    154 # A call-without-arguments declaration.
    155 #
    156 /^[a-zA-Z]+[a-zA-Z0-9\-]*[ \t]*;[ \t]*$/ {
    157 	# strip the trailing ;
    158 	call_name = $1
    159 	gsub(";$", "", call_name)
    160 
    161 	start_decl(call_name)
    162 
    163 	emit_binding("")
    164 	emit_name_macro()
    165 	emit_invoke_macro("generic", "", "NULL")
    166 
    167 	next
    168 }
    169 #
    170 # End of a declaration.  Wrap up the structure declaration and emit
    171 # the binding information.
    172 #
    173 /^}[ \t]*;[ \t]*$/ {
    174 	if (state != "expecting-decl-end") {
    175 		print "unexpected end of declaration at line " NR \
    176 		    > "/dev/stderr"
    177 		exit 1
    178 	}
    179 
    180 	# Terminate the args structure declaration.
    181 	printf("};\n")
    182 
    183 	printf("\n")
    184 	emit_binding("binding")
    185 	emit_name_macro()
    186 	emit_invoke_macro("binding", "(_args_)", "(_args_)")
    187 
    188 	state = "expecting-decl-start"
    189 
    190 	next
    191 }
    192 #
    193 # Default action is to simply emit the line as it exists in the source
    194 # file.
    195 #
    196 {
    197 	print $0
    198 }
    199 END {
    200 	if (state != "expecting-decl-start") {
    201 		print "unexpected end of file at line " NR \
    202 		    > "/dev/stderr"
    203 		exit 1
    204 	}
    205 
    206 	# Emit the trailing header guard.
    207 	printf("\n#endif /* _%s_CALLS_H_ */\n", subsystem_ub_uc)
    208 }
    209