1#!/bin/sh
2
3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4#
5# Copyright (c) 2000, Bruce Evans <bde@freebsd.org>
6# Copyright (c) 2018, Jeff Roberson <jeff@freebsd.org>
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27# SUCH DAMAGE.
28#
29# $FreeBSD$
30
31usage()
32{
33	echo "usage: genoffset [-o outfile] objfile"
34	exit 1
35}
36
37
38work()
39{
40	echo "#ifndef _OFFSET_INC_"
41	echo "#define _OFFSET_INC_"
42	echo "#if !defined(GENOFFSET) && (!defined(KLD_MODULE) || defined(KLD_TIED))"
43	${NM:='nm'} ${NMFLAGS} "$1" | ${AWK:='awk'} '
44	/ C .*_datatype_*/ {
45		type = substr($3, match($3, "_datatype_") + length("_datatype_"))
46	}
47	/ C .*_parenttype_*/ {
48		parent = substr($3, match($3, "_parenttype_") + length("_parenttype_"))
49	}
50	/ C .*sign$/ {
51		sign = substr($1, length($1) - 3, 4)
52		sub("^0*", "", sign)
53		if (sign != "")
54			sign = "-"
55	}
56	/ C .*w0$/ {
57		w0 = substr($1, length($1) - 3, 4)
58	}
59	/ C .*w1$/ {
60		w1 = substr($1, length($1) - 3, 4)
61	}
62	/ C .*w2$/ {
63		w2 = substr($1, length($1) - 3, 4)
64	}
65	/ C .*w3$/ {
66		w3 = substr($1, length($1) - 3, 4)
67		w = w3 w2 w1 w0
68		sub("^0*", "", w)
69		if (w == "")
70			w = "0"
71		hex = ""
72		if (w != "0")
73			hex = "0x"
74		sub("w3$", "", $3)
75		member = tolower($3)
76		# This still has minor problems representing INT_MIN, etc. 
77		# E.g.,
78		# with 32-bit 2''s complement ints, this prints -0x80000000,
79		# which has the wrong type (unsigned int).
80		offset = sprintf("%s%s%s", sign, hex, w)
81
82		structures[parent] = sprintf("%s%s %s %s\n",
83		    structures[parent], offset, type, member)
84	}
85	END {
86		for (struct in structures) {
87			printf("struct %s_lite {\n", struct);
88			n = split(structures[struct], members, "\n")
89			for (i = 1; i < n; i++) {
90				for (j = i + 1; j < n; j++) {
91					split(members[i], ivar, " ")
92					split(members[j], jvar, " ")
93					if (jvar[1] < ivar[1]) {
94						tmp = members[i]
95						members[i] = members[j]
96						members[j] = tmp
97					}
98				}
99			}
100			off = "0"
101			for (i = 1; i < n; i++) {
102				split(members[i], m, " ")
103				printf "\tu_char\tpad_%s[%s - %s];\n", m[3], m[1], off
104				printf "\t%s\t%s;\n", m[2], m[3]
105				off = sprintf("(%s + sizeof(%s))", m[1], m[2])
106			}
107			printf("};\n");
108		}
109	}
110	'
111
112	echo "#endif"
113	echo "#endif"
114}
115
116
117#
118#MAIN PROGGRAM
119#
120use_outfile="no"
121while getopts "o:" option
122do
123	case "$option" in
124	o)	outfile="$OPTARG"
125		use_outfile="yes";;
126	*)	usage;;
127	esac
128done
129shift $(($OPTIND - 1))
130case $# in
1311)	;;
132*)	usage;;
133esac
134
135if [ "$use_outfile" = "yes" ]
136then
137	work $1  3>"$outfile" >&3 3>&-
138else
139	work $1
140fi
141
142