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