1#!/bin/sh
2#
3# Copyright (c) 2014, 2019, 2020 Juniper Networks, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27#
28
29#
30# Convert a NIC driver to use the procdural API.
31# It doesn't take care of all the # cases yet,
32# but still does about 95% of work.
33#
34# Author: Sreekanth Rupavatharam
35#
36
37MAX_PASSES=100
38
39if [ $# -lt 1 ]
40then
41	echo " $0 <driver source (e.g., if_em.c)>";
42	exit 1;
43fi
44
45# XXX - This needs to change if the data structure uses different name
46__ifp__="ifp";
47
48file=$1
49
50rotateCursor() {
51	case $toggle in
52	1) c="\\" ;;
53	2) c="|" ;;
54	3) c="/" ;;
55	*) c="-" ;;
56	esac
57	toggle=$(((toggle + 1) % 4))
58	printf " %s \b\b\b" $c
59}
60
61# Handle the case where $__ifp__->if_blah = XX;
62handle_set() {
63	if echo $line | grep "$__ifp__->.* = " > /dev/null 2>&1
64	then
65		if echo $line | grep "\[$__ifp__->.* = " > /dev/null 2>&1; then
66			# Special case of array[ifp->member] = value
67			return 1
68		fi
69		word=`echo $line | awk -F "if_" ' { print $2 }' | awk -F" =" '{ print $1 }'`
70		value=`echo $line | awk -F "=" '{ print $2 }' | sed -e 's/;//g'`
71		new=`echo if_set$word"\($__ifp__,"$value");"`
72		new=`echo $new | sed -e 's/&/\\\&/'`
73		old=`echo $line|sed -e 's/^[ 	]*//'`
74		line=`echo $line| sed -e's/'$old'/'$new'/g'`
75		return 0
76	fi
77	return 1
78}
79
80handle_inc() {
81	if echo $line | grep "$__ifp__->.*++\|++$__ifp__->.*" > /dev/null 2>&1
82	then
83		word=`echo $line | awk -F"if_" '{ print $2 }'|awk -F"\+" '{ print $1}'`
84		value=' 1';
85		old=`echo $line|sed -e 's/^[ 	]*//'`
86		new=`echo if_inc$word"\($__ifp__,"$value");"`
87		new=`echo $new | sed -e 's/&/\\\&/'`
88		line=`echo $line| sed -e's/'$old'/'$new'/g'`
89		return 0;
90	fi
91	return 1;
92}
93
94handle_add() {
95	if echo $line | grep "$__ifp__->.*+= " > /dev/null 2>&1
96	then
97		word=`echo $line | awk -F"if_" '{ print $2 }'|awk '{ print $1}'`
98		value=`echo $line | awk -F"=" '{ print $2}' | sed -e 's/;//g'`
99		new=`echo if_inc$word"\($__ifp__,$value);"`
100		new=`echo $new | sed -e 's/&/\\\&/'`
101		old=`echo $line|sed -e 's/^[ 	]*//'`
102		line=`echo $line| sed -e's/'$old'/'$new'/g'`
103		return 0
104	fi
105	return 1;
106
107}
108
109handle_or() {
110	if echo $line | grep "$__ifp__->.*|= " > /dev/null 2>&1
111	then
112		word=`echo $line | awk -F"if_" '{ print $2 }'|awk '{ print $1}'`
113		value=`echo $line | awk -F"=" '{ print $2}' | sed -e 's/;//g'`
114		new=`echo if_set${word}bit"($__ifp__,$value, 0);"`
115		new=`echo $new | sed -e 's/&/\\\&/'`
116		#line=`echo $line|sed -e 's/&/\\&/'`
117		old=`echo $line|sed -e 's/^[ 	]*//'`
118		line=`echo $line| sed -e's/'$old'/'$new'/g'`
119		return 0;
120	fi
121	return 1;
122
123}
124
125handle_and() {
126	if echo $line |grep "$__ifp__->.*&= " > /dev/null 2>&1
127	then
128		word=`echo $line | awk -F"if_" '{ print $2 }'|awk '{ print $1}'`
129		value=`echo $line | awk -F"=" '{ print $2}' | sed -e 's/;//g'`
130		value=`echo $value | sed -e's/~//g'`
131		new=`echo if_set${word}bit"\($__ifp__, 0,$value);"`
132		new=`echo $new | sed -e 's/&/\\\&/'`
133		old=`echo $line|sed -e 's/^[ 	]*//'`
134		line=`echo $line| sed -e's/'$old'/'$new'/g'`
135		return 0;
136	fi
137	return 1;
138
139}
140
141handle_toggle() {
142	if echo $line | grep "\^=" > /dev/null 2>&1
143	then
144		line=`echo $line | sed -e 's/'"$__ifp__"'->if_\(.*\) ^=\(.*\);/if_toggle\1('"$__ifp__"',\2);/g'`
145		return 0;
146	fi
147	return 1
148
149}
150
151# XXX - this needs updating
152handle_misc() {
153	if echo $line | grep "$__ifp__->\(if_capabilities\|if_flags\|if_softc\|if_capenable\|if_hwassist\|if_mtu\|if_drv_flags\|if_index\|if_alloctype\|if_dname\|if_xname\|if_addr\|if_hw_tsomax\|if_hw_tsomaxsegcount\|if_hw_tsomaxsegsize\)" > /dev/null 2>&1
154	then
155		word=`echo $line |awk -F"$__ifp__->if_" '{ print $2 }' | \
156			sed -e's/[^a-zA-Z0-9_]/\@/'|awk -F"\@" '{ print $1}'`
157		old=`echo "$__ifp__->if_"${word}`
158		new=`echo "if_get"${word}"($__ifp__)"`
159		new=`echo $new | sed -e 's/&/\\\&/'`
160		line=`echo $line| sed -e's/'$old'/'$new'/g'`
161		return 0;
162	fi
163	return 1;
164
165}
166
167replace_str ()
168{
169	orig=$1
170	new=$2
171
172	if echo $line | grep "$orig" > /dev/null 2>&1
173	then
174		line=`echo $line | sed -e "s|$orig|$new|"`
175	else
176		return 1
177	fi
178}
179
180handle_special ()
181{
182	replace_str "(\*$__ifp__->if_input)" "if_input" || \
183	replace_str "IFQ_DRV_IS_EMPTY(&$__ifp__->if_snd)" \
184		"if_sendq_empty($__ifp__)" || \
185	replace_str "IFQ_DRV_PREPEND(&$__ifp__->if_snd" \
186		"if_sendq_prepend($__ifp__" || \
187	replace_str "IFQ_SET_READY(&$__ifp__->if_snd)" \
188		"if_setsendqready($__ifp__)" || \
189	replace_str "VLAN_CAPABILITIES($__ifp__)" \
190		"if_vlancap($__ifp__)" || \
191	replace_str "IFQ_SET_MAXLEN(&$__ifp__->if_snd," \
192		"if_setsendqlen($__ifp__," || \
193	replace_str "IFQ_DRV_DEQUEUE(&$__ifp__->if_snd, \(.*\))" \
194		"\1 = if_dequeue($__ifp__)"
195	replace_str "$__ifp__->if_vlantrunk != NULL" \
196		"if_vlantrunkinuse($__ifp__)"
197}
198
199handle_ifps() {
200	handle_set || handle_inc || handle_add || handle_or || handle_and || \
201	handle_toggle || handle_misc || handle_special
202}
203
204handle_renames ()
205{
206	replace_str "if_setinit(" "if_setinitfn(" || \
207	replace_str "if_setioctl(" "if_setioctlfn(" || \
208	replace_str "if_setqflush(" "if_setqflushfn(" || \
209	replace_str "if_settransmit(" "if_settransmitfn(" || \
210	replace_str "if_getdrv_flags(" "if_getdrvflags(" || \
211	replace_str "if_setdrv_flagsbit(" "if_setdrvflagbits(" || \
212	replace_str "if_setstart(" "if_setstartfn(" || \
213	replace_str "if_sethwassistbit(" "if_sethwassistbits(" || \
214	replace_str "ifmedia_init(" "ifmedia_init_drv("
215}
216
217check_ifp()
218{
219	case "$line" in
220	*"${__ifp__}->"*) return 0;; # Still an ifp to convert
221	esac
222	return 1
223}
224
225add_failed ()
226{
227	line="$line /* ${FAIL_PAT} */"
228	return 1
229}
230
231if [ -e $file.tmp ]
232then
233	rm $file.tmp
234fi
235IFS=
236echo -n "Conversion for $file started, please wait: "
237FAIL_PAT="XXX - IFAPI"
238count=0
239while read -r line
240do
241	rotateCursor
242
243	# There is an ifp, we need to process it
244	passes=0
245	while check_ifp
246	do
247		if handle_ifps
248		then
249			handle_renames
250		else
251			add_failed
252			break
253		fi
254		passes=$((passes + 1))
255		if [ $passes -ge $MAX_PASSES ]; then
256			add_failed
257			break
258		fi
259	done
260
261	# Replace the ifnet * with if_t
262	case "$line" in
263	*"struct ifnet"*)
264		line=`echo $line | sed -e 's/struct ifnet[ \t]*\*/if_t /g'` ;;
265	*"IF_LLADDR("*)
266		line=`echo $line | sed -e 's/IF_LLADDR(/if_getlladdr(/g'` ;;
267	esac
268	printf "%s\n" "$line" >> $file.tmp
269done < $1
270echo ""
271count=`grep $FAIL_PAT $file.tmp | wc -l`
272if [ $count -gt 0 ]
273then
274	echo "$count lines could not be converted to IFAPI"
275	echo "Look for /* $FAIL_PAT */ in the converted file"
276fi
277echo "original $file  has been moved to $file.orig"
278mv $file $file.orig
279mv $file.tmp $file
280