1test -n "$1" -a -n "$2" -a -n "$3"
2set -ef
3
4SED=sed
5if test -x /usr/xpg4/bin/sed; then
6	SED=/usr/xpg4/bin/sed
7fi
8if test -z ${PYTHON}; then
9	PYTHON=`/usr/bin/env python`
10fi
11if test -z ${PYTHON}; then
12	echo "Python not found"
13	exit 1
14fi
15
16get_fields ()
17{
18	local level=1 aggr=0 name= fields=
19	for token in $2
20	do
21		case "$token" in
22		struct|union)
23			test $level != 1 || aggr=1 fields= name=
24			;;
25		"{")
26			level=$(expr $level + 1)
27			;;
28		"}")
29			level=$(expr $level - 1)
30			if [ $level = 1 -a $name = $1 ]
31			then
32				echo "$fields }"
33				return 0
34			fi
35			;;
36		[a-zA-Z_]*)
37			test $aggr = 0 -o -n "$name" || name="$token"
38			;;
39		esac
40		test $aggr = 0 || fields="$fields $token"
41	done
42}
43
44get_typedefs ()
45{
46	local level=1 state=
47	for token in $1
48	do
49		case "$token" in
50		typedef)
51			test $level != 1 || state=1
52			;;
53		COMPAT_HANDLE\(*\))
54			test $level != 1 -o "$state" != 1 || state=2
55			;;
56		[\{\[])
57			level=$(expr $level + 1)
58			;;
59		[\}\]])
60			level=$(expr $level - 1)
61			;;
62		";")
63			test $level != 1 || state=
64			;;
65		[a-zA-Z_]*)
66			test $level != 1 -o "$state" != 2 || echo "$token"
67			;;
68		esac
69	done
70}
71
72build_enums ()
73{
74	local level=1 kind= fields= members= named= id= token
75	for token in $2
76	do
77		case "$token" in
78		struct|union)
79			test $level != 2 || fields=" "
80			kind="$token;$kind"
81			;;
82		"{")
83			level=$(expr $level + 1)
84			;;
85		"}")
86			level=$(expr $level - 1)
87			if [ $level = 1 ]
88			then
89				if [ "${kind%%;*}" = union ]
90				then
91					echo
92					echo "enum XLAT_$1 {"
93					for m in $members
94					do
95						echo "    XLAT_${1}_$m,"
96					done
97					echo "};"
98				fi
99				return 0
100			elif [ $level = 2 ]
101			then
102				named='?'
103			fi
104			;;
105		[a-zA-Z]*)
106			id=$token
107			if [ -n "$named" -a -n "${kind#*;}" ]
108			then
109				build_enums ${1}_$token "$fields"
110				named='!'
111			fi
112			;;
113		",")
114			test $level != 2 || members="$members $id"
115			;;
116		";")
117			test $level != 2 || members="$members $id"
118			test -z "$named" || kind=${kind#*;}
119			named=
120			;;
121		esac
122		test -z "$fields" || fields="$fields $token"
123	done
124}
125
126handle_field ()
127{
128	if [ -z "$5" ]
129	then
130		echo " \\"
131		if [ -z "$4" ]
132		then
133			printf %s "$1(_d_)->$3 = (_s_)->$3;"
134		else
135			printf %s "$1XLAT_${2}_HNDL_$(echo $3 | $SED 's,\.,_,g')(_d_, _s_);"
136		fi
137	elif [ -z "$(echo "$5" | $SED 's,[^{}],,g')" ]
138	then
139		local tag=$(echo "$5" | ${PYTHON} -c '
140import re,sys
141for line in sys.stdin.readlines():
142    print re.subn(r"\s*(struct|union)\s+(compat_)?(\w+)\s.*", r"\3", line)[0].rstrip()
143')
144		echo " \\"
145		printf %s "${1}XLAT_$tag(&(_d_)->$3, &(_s_)->$3);"
146	else
147		local level=1 kind= fields= id= array= arrlvl=1 array_type= type= token
148		for token in $5
149		do
150			case "$token" in
151			struct|union)
152				test $level != 2 || fields=" "
153				if [ $level = 1 ]
154				then
155					kind=$token
156					if [ $kind = union ]
157					then
158						echo " \\"
159						printf %s "${1}switch ($(echo $3 | $SED 's,\.,_,g')) {"
160					fi
161				fi
162				;;
163			"{")
164				level=$(expr $level + 1) id=
165				;;
166			"}")
167				level=$(expr $level - 1) id=
168				if [ $level = 1 -a $kind = union ]
169				then
170					echo " \\"
171					printf %s "$1}"
172				fi
173				;;
174			"[")
175				if [ $level != 2 -o $arrlvl != 1 ]
176				then
177					:
178				elif [ -z "$array" ]
179				then
180					array=" "
181				else
182					array="$array;"
183				fi
184				arrlvl=$(expr $arrlvl + 1)
185				;;
186			"]")
187				arrlvl=$(expr $arrlvl - 1)
188				;;
189			COMPAT_HANDLE\(*\))
190				if [ $level = 2 -a -z "$id" ]
191				then
192					type=${token#COMPAT_HANDLE?}
193					type=${type%?}
194					type=${type#compat_}
195				fi
196				;;
197			compat_domain_handle_t)
198				if [ $level = 2 -a -z "$id" ]
199				then
200					array_type=$token
201				fi
202				;;
203			[a-zA-Z]*)
204				if [ -z "$id" -a -z "$type" -a -z "$array_type" ]
205				then
206					for id in $typedefs
207					do
208						test $id != "$token" || type=$id
209					done
210					if [ -z "$type" ]
211					then
212						id=$token
213					else
214						id=
215					fi
216				else
217					id=$token
218				fi
219				;;
220			[\,\;])
221				if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
222				then
223					if [ $kind = union ]
224					then
225						echo " \\"
226						printf %s "${1}case XLAT_${2}_$(echo $3.$id | $SED 's,\.,_,g'):"
227						handle_field "$1    " $2 $3.$id "$type" "$fields"
228					elif [ -z "$array" -a -z "$array_type" ]
229					then
230						handle_field "$1" $2 $3.$id "$type" "$fields"
231					elif [ -z "$array" ]
232					then
233						copy_array "    " $3.$id
234					else
235						handle_array "$1" $2 $3.$id "${array#*;}" "$type" "$fields"
236					fi
237					test "$token" != ";" || fields= id= type=
238					array=
239					if [ $kind = union ]
240					then
241						echo " \\"
242						printf %s "$1    break;"
243					fi
244				fi
245				;;
246			*)
247				if [ -n "$array" ]
248				then
249					array="$array $token"
250				fi
251				;;
252			esac
253			test -z "$fields" || fields="$fields $token"
254		done
255	fi
256}
257
258copy_array ()
259{
260	echo " \\"
261	echo "${1}if ((_d_)->$2 != (_s_)->$2) \\"
262	printf %s "$1    memcpy((_d_)->$2, (_s_)->$2, sizeof((_d_)->$2));"
263}
264
265handle_array ()
266{
267	local i="i$(echo $4 | $SED 's,[^;], ,g' | wc -w | $SED 's,[[:space:]]*,,g')"
268	echo " \\"
269	echo "$1{ \\"
270	echo "$1    unsigned int $i; \\"
271	printf %s "$1    for ($i = 0; $i < "${4%%;*}"; ++$i) {"
272	if [ "$4" = "${4#*;}" ]
273	then
274		handle_field "$1        " $2 $3[$i] "$5" "$6"
275	else
276		handle_array "$1        " $2 $3[$i] "${4#*;}" "$5" "$6"
277	fi
278	echo " \\"
279	echo "$1    } \\"
280	printf %s "$1}"
281}
282
283build_body ()
284{
285	echo
286	printf %s "#define XLAT_$1(_d_, _s_) do {"
287	local level=1 fields= id= array= arrlvl=1 array_type= type= token
288	for token in $2
289	do
290		case "$token" in
291		struct|union)
292			test $level != 2 || fields=" "
293			;;
294		"{")
295			level=$(expr $level + 1) id=
296			;;
297		"}")
298			level=$(expr $level - 1) id=
299			;;
300		"[")
301			if [ $level != 2 -o $arrlvl != 1 ]
302			then
303				:
304			elif [ -z "$array" ]
305			then
306				array=" "
307			else
308				array="$array;"
309			fi
310			arrlvl=$(expr $arrlvl + 1)
311			;;
312		"]")
313			arrlvl=$(expr $arrlvl - 1)
314			;;
315		COMPAT_HANDLE\(*\))
316			if [ $level = 2 -a -z "$id" ]
317			then
318				type=${token#COMPAT_HANDLE?}
319				type=${type%?}
320				type=${type#compat_}
321			fi
322			;;
323		compat_domain_handle_t)
324			if [ $level = 2 -a -z "$id" ]
325			then
326				array_type=$token
327			fi
328			;;
329		[a-zA-Z_]*)
330			if [ -n "$array" ]
331			then
332				array="$array $token"
333			elif [ -z "$id" -a -z "$type" -a -z "$array_type" ]
334			then
335				for id in $typedefs
336				do
337					test $id != "$token" || type=$id
338				done
339				if [ -z "$type" ]
340				then
341					id=$token
342				else
343					id=
344				fi
345			else
346				id=$token
347			fi
348			;;
349		[\,\;])
350			if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
351			then
352				if [ -z "$array" -a -z "$array_type" ]
353				then
354					handle_field "    " $1 $id "$type" "$fields"
355				elif [ -z "$array" ]
356				then
357					copy_array "    " $id
358				else
359					handle_array "    " $1 $id "${array#*;}" "$type" "$fields"
360				fi
361				test "$token" != ";" || fields= id= type=
362				array=
363			fi
364			;;
365		*)
366			if [ -n "$array" ]
367			then
368				array="$array $token"
369			fi
370			;;
371		esac
372		test -z "$fields" || fields="$fields $token"
373	done
374	echo " \\"
375	echo "} while (0)"
376}
377
378check_field ()
379{
380	if [ -z "$(echo "$4" | $SED 's,[^{}],,g')" ]
381	then
382		echo "; \\"
383		local n=$(echo $3 | $SED 's,[^.], ,g' | wc -w | $SED 's,[[:space:]]*,,g')
384		if [ -n "$4" ]
385		then
386			for n in $4
387			do
388				case $n in
389				struct|union)
390					;;
391				[a-zA-Z_]*)
392					printf %s "    CHECK_${n#xen_}"
393					break
394					;;
395				*)
396					echo "Malformed compound declaration: '$n'" >&2
397					exit 1
398					;;
399				esac
400			done
401		elif [ $n = 0 ]
402		then
403			printf %s "    CHECK_FIELD_($1, $2, $3)"
404		else
405			printf %s "    CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | $SED 's!\.!, !g'))"
406		fi
407	else
408		local level=1 fields= id= token
409		for token in $4
410		do
411			case "$token" in
412			struct|union)
413				test $level != 2 || fields=" "
414				;;
415			"{")
416				level=$(expr $level + 1) id=
417				;;
418			"}")
419				level=$(expr $level - 1) id=
420				;;
421			[a-zA-Z]*)
422				id=$token
423				;;
424			[\,\;])
425				if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
426				then
427					check_field $1 $2 $3.$id "$fields"
428					test "$token" != ";" || fields= id=
429				fi
430				;;
431			esac
432			test -z "$fields" || fields="$fields $token"
433		done
434	fi
435}
436
437build_check ()
438{
439	echo
440	echo "#define CHECK_$1 \\"
441	local level=1 fields= kind= id= arrlvl=1 token
442	for token in $2
443	do
444		case "$token" in
445		struct|union)
446			if [ $level = 1 ]
447			then
448				kind=$token
449				printf %s "    CHECK_SIZE_($kind, $1)"
450			elif [ $level = 2 ]
451			then
452				fields=" "
453			fi
454			;;
455		"{")
456			level=$(expr $level + 1) id=
457			;;
458		"}")
459			level=$(expr $level - 1) id=
460			;;
461		"[")
462			arrlvl=$(expr $arrlvl + 1)
463			;;
464		"]")
465			arrlvl=$(expr $arrlvl - 1)
466			;;
467		[a-zA-Z_]*)
468			test $level != 2 -o $arrlvl != 1 || id=$token
469			;;
470		[\,\;])
471			if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
472			then
473				check_field $kind $1 $id "$fields"
474				test "$token" != ";" || fields= id=
475			fi
476			;;
477		esac
478		test -z "$fields" || fields="$fields $token"
479	done
480	echo ""
481}
482
483list="$($SED -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)"
484fields="$(get_fields $(echo $2 | $SED 's,^compat_xen,compat_,') "$list")"
485if [ -z "$fields" ]
486then
487	echo "Fields of '$2' not found in '$3'" >&2
488	exit 1
489fi
490name=${2#compat_}
491name=${name#xen}
492case "$1" in
493"!")
494	typedefs="$(get_typedefs "$list")"
495	build_enums $name "$fields"
496	build_body $name "$fields"
497	;;
498"?")
499	build_check $name "$fields"
500	;;
501*)
502	echo "Invalid translation indicator: '$1'" >&2
503	exit 1
504	;;
505esac
506