Given the need for an audit of macro ordering in libtool, I decided I needed all the help and information I could get.
So first, I went through the fun of sh -u configure adding environment variables until I hit bugs. I also wrote a hacky script to find uninitialized uses by unleashing weird sed scripts upon `configure' -- attached. Both target almost the same thing, with the difference being that the former only analyzes the actual code path taken, whereas the latter is a pretty bad heuristic but covers all code without actually knowing anything about logic, and being blissfully ignorant to shell functions and other nonlinear execution order. IOW, the script is primarily useful for autoconf output. These two tools complement each other, erm, have both uncovered issues.. Cheers, Ralf
#! /bin/sh # use-before-set - find some uses of shell vars before setting them # Copyright (C) 2005 # Ralf Wildenhues <[EMAIL PROTECTED]> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This script assumes GNU sed, and mostly POSIX shell. # TODO: parse multiple assignments per line # TODO: parse multiple for loops per line (or don't) # TODO: parse ${foo:=bar} (not portable, so no issue in configure scripts) # # NOTE: This script does not understand 'eval', nor does it follow # "interesting" quotation or escaping mechanisms. # NOTE: This script has no idea of shell functions or any other # nonlinear execution paths. Use `sh -u'. # Set this to '#' if you want the second sed script # to see single-quoted content. (You do, trust me.) skip_single_quoted='#' # Ignore these variables, they are user-provided. # Note: separate with spaces, no newlines in here! skip_vars="SHELL CPPFLAGS LDFLAGS" # These variables are user-provided; it's ok to use them # provided the first use looks like the Autoconf-precious-vars test. # Note: separate with spaces, no newlines in here! precious_vars="\ CC CPP CFLAGS CXX CXXCPP CXXFLAGS CXXCPPFLAGS LD LDCXX LIBS \ F77 FFLAGS FC FCFLAGS GCJ GCJFLAGS RC \ AWK EGREP GREP INSTALL MAKE \ AR AS DLLTOOL NM OBJDUMP RANLIB STRIP" ### should not need to modify anything below this line ### # fail on first error set -e set -u # we rely on ASCII sorting; and please: make it fast LC_ALL=C export LC_ALL if test $# -lt 1 then echo >&2 "usage: $0 script-to-check" exit 1 fi last_param= # Find all probable assignments, # pair them up with corresponding line numbers. # sort the resulting list by parameter name, then line # (in order to pick only the first one later). sed -n < "$1" ' # skip comments /^[ ]*#/b next # parse "foo=bar" /[a-zA-Z_][a-zA-Z_0-9]*=/ { s/.*[^a-zA-Z_]\([a-zA-Z_][a-zA-Z_0-9]*\)=.*/\1/ s/^\([a-zA-Z_][a-zA-Z_0-9]*\)=.*/\1/ p;= } # parse for loop variable assignment /\<for[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*\([ ][ ]*in\|$\)/ { s/.*for[ ][ ]*\([a-zA-Z_][a-zA-Z_0-9]*\).*/\1/ p;= } # parse read variable assignments /\<read[ ][ ]*[a-zA-Z_]/ { s/.*read[ ][ ]*\([a-zA-Z_]\)/\1/ T :read h s/\([a-zA-Z_][a-zA-Z_0-9]*\).*/\1/ p = T x s/[a-zA-Z_][a-zA-Z_0-9]*[ ][ ]*// t read } :next ' | sed 'N;s/\n/ /' | sort -s -k1,1 -k2,2n | while read param line do if test "$param" = "$last_param"; then continue; fi last_param=$param case " $skip_vars " in (*" $param "*) continue;; esac case " $precious_vars " in (*" $param "*) skip_precious= ;; (*) skip_precious='#' ;; esac prevline=`expr $line - 1` # Now, find any probable use of the variable before the assignment. sed -n < "$1" " # end at the line before the assignment ${prevline} q # skip comments /^[ ]*#/ b # if desired, skip single quoted areas ${skip_single_quoted} s/'[^']*'//g # find parameter expansion /\(\\\$$param\>\)\|\(\\\${#\{0,1\}$param[#%+-:}]\)/ { # for precious variables: end searching without error, # when the specific autoconf snippet is found ${skip_precious} /\<if test -[nz] \"\\\$$param\"; then/ q # autoconf cache variable test idiom: /\\\${$param+set}/ b # ok, we have a possible bug. i\ ERROR: $param used before set at line = p } " | sed 'N;N;s/\n/ /' done # vi:set sw=2: