1#! /bin/sh
2
3#
4# runlex.sh
5# Script to run Lex/Flex.
6# First argument is the (quoted) name of the command; if it's null, that
7# means that neither Flex nor Lex was found, so we report an error and
8# quit.
9#
10# @(#) $Header: /tcpdump/master/libpcap/runlex.sh,v 1.4 2007-12-31 03:38:39 guy Exp $
11#
12
13#
14# Get the name of the command to run, and then shift to get the arguments.
15#
16if [ $# -eq 0 ]
17then
18	echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
19	exit 1
20fi
21LEX="$1"
22shift
23
24#
25# Check whether we have Lex or Flex.
26#
27if [ -z "${LEX}" ]
28then
29	echo "Neither lex nor flex was found" 1>&2
30	exit 1
31fi
32
33#
34# Process the flags.  We don't use getopt because we don't want to
35# embed complete knowledge of what options are supported by Lex/Flex.
36#
37flags=""
38outfile=lex.yy.c
39while [ $# -ne 0 ]
40do
41	case "$1" in
42
43	-o*)
44		#
45		# Set the output file name.
46		#
47		outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
48		;;
49
50	-*)
51		#
52		# Add this to the list of flags.
53		#
54		flags="$flags $1"
55		;;
56
57	--|*)
58		#
59		# End of flags.
60		#
61		break
62		;;
63	esac
64	shift
65done
66
67#
68# Is it Lex, or is it Flex?
69#
70if [ "${LEX}" = flex ]
71then
72	#
73	# It's Flex.
74	#
75	have_flex=yes
76
77	#
78	# Does it support the --noFUNCTION options?  If so, we pass
79	# --nounput, as at least some versions that support those
80	# options don't support disabling yyunput by defining
81	# YY_NO_UNPUT.
82	#
83	if flex --help | egrep noFUNCTION >/dev/null
84	then
85		flags="$flags --nounput"
86
87		#
88		# Does it support -R, for generating reentrant scanners?
89		# If so, we're not currently using that feature, but
90		# it'll generate some unused functions anyway - and there
91		# won't be any header file declaring them, so there'll be
92		# defined-but-not-declared warnings.  Therefore, we use
93		# --noFUNCTION options to suppress generating those
94		# functions.
95		#
96		if flex --help | egrep reentrant >/dev/null
97		then
98			flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
99		fi
100	fi
101else
102	#
103	# It's Lex.
104	#
105	have_flex=no
106fi
107
108#
109# OK, run it.
110# If it's lex, it doesn't support -o, so we just write to
111# lex.yy.c and, if it succeeds, rename it to the right name,
112# otherwise we remove lex.yy.c.
113# If it's flex, it supports -o, so we use that - flex with -P doesn't
114# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
115#
116if [ $have_flex = yes ]
117then
118	${LEX} $flags -o"$outfile" "$@"
119
120	#
121	# Did it succeed?
122	#
123	status=$?
124	if [ $status -ne 0 ]
125	then
126		#
127		# No.  Exit with the failing exit status.
128		#
129		exit $status
130	fi
131
132	#
133	# Flex has the annoying habit of stripping all but the last
134	# component of the "-o" flag argument and using that as the
135	# place to put the output.  This gets in the way of building
136	# in a directory different from the source directory.  Try
137	# to work around this.
138	#
139	# Is the outfile where we think it is?
140	#
141	outfile_base=`basename "$outfile"`
142	if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
143	then
144		#
145		# No, it's not, but it is in the current directory.  Put it
146		# where it's supposed to be.
147		#
148		mv "$outfile_base" "$outfile"
149
150		#
151		# Did that succeed?
152		#
153		status=$?
154		if [ $status -ne 0 ]
155		then
156			#
157			# No.  Exit with the failing exit status.
158			#
159			exit $status
160		fi
161	fi
162else
163	${LEX} $flags "$@"
164
165	#
166	# Did it succeed?
167	#
168	status=$?
169	if [ $status -ne 0 ]
170	then
171		#
172		# No.  Get rid of any lex.yy.c file we generated, and
173		# exit with the failing exit status.
174		#
175		rm -f lex.yy.c
176		exit $status
177	fi
178
179	#
180	# OK, rename lex.yy.c to the right output file.
181	#
182	mv lex.yy.c "$outfile" 
183
184	#
185	# Did that succeed?
186	#
187	status=$?
188	if [ $status -ne 0 ]
189	then
190		#
191		# No.  Get rid of any lex.yy.c file we generated, and
192		# exit with the failing exit status.
193		#
194		rm -f lex.yy.c
195		exit $status
196	fi
197fi
198
199#
200# OK, now let's generate a header file declaring the relevant functions
201# defined by the .c file; if the .c file is .../foo.c, the header file
202# will be .../foo.h.
203#
204# This works around some other Flex suckage, wherein it doesn't declare
205# the lex routine before defining it, causing compiler warnings.
206# XXX - newer versions of Flex support --header-file=, to generate the
207# appropriate header file.  With those versions, we should use that option.
208#
209
210#
211# Get the name of the prefix; scan the source files for a %option prefix
212# line.  We use the last one.
213#
214prefix=`sed -n 's/%option[ 	][ 	]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
215if [ ! -z "$prefix" ]
216then
217	prefixline="#define yylex ${prefix}lex"
218fi
219
220#
221# Construct the name of the header file.
222#
223header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
224
225#
226# Spew out the declaration.
227#
228cat <<EOF >$header_file
229/* This is generated by runlex.sh.  Do not edit it. */
230$prefixline
231#ifndef YY_DECL
232#define YY_DECL int yylex(void)
233#endif  
234YY_DECL;
235EOF
236