#!/bin/sh # # SYNOPSIS # fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD # # COPYRIGHT # Copyright (C) 1993, 1994, 1997, 1998, 2002, 2003 # Free Software Foundation, Inc. # This file is part of GCC. # # GCC 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, or (at your option) # any later version. # # GCC is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GCC; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # DESCRIPTION # Adjunct script for GCC to populate a directory with ANSI, # Posix.1, and C++ compatible header files. # # Each file found under SOURCE-DIR-ALL is analyzed and "fixed." # Only standard ANSI/POSIX files found under SOURCE-DIR-STD # are analyzed and "fixed." # The SOURCE-DIRs are searched in order; a file found # under multiple SOURCE-DIRs is only handled for the first one. # # STRATEGY # Each include file is fed through cpp, and the scan-decls program # parses it, and emits any found function declarations. # The fix-header program analyzes the scan-decls output, # together with the original include file, and writes a "fixed" # include file, if needed. # # The comment at the beginning of fix-header.c lists specifically # what kind of changes are made. # # NOTE # Some file space will be wasted, because the original header # files are copied. An earlier version just included the original # by "reference", using GNU cpp's #include_next mechanism. # This is currently not done, partly because #include_next is # fragile (susceptible to version incompatibilities, and depends # and GCC-specific features), and partly for performance reasons. # # AUTHORS # Ron Guilmette (rfg@netcom.com) (original idea and code) # Per Bothner (bothner@cygnus.com) (major re-write) dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'` progname=`echo "$0" | sed 's,.*/,,'` original_dir=`${PWDCMD-pwd}` FIX_HEADER=${FIX_HEADER-$original_dir/fix-header} DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}" if mkdir -p . 2> /dev/null; then # Great, mkdir accepts -p mkinstalldirs="mkdir -p" else # We expect mkinstalldirs to be passed in the environment. # If it is not, assume it is in the directory that contains this script. mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"} if $mkinstalldirs . 2> /dev/null; then : else # But, in case of failure, fallback to plain mkdir, and hope it works mkinstalldirs=mkdir fi fi if [ `echo $1 | wc -w` = 0 ] ; then echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \] exit 1 fi std_files="ctype.h dirent.h errno.h curses.h fcntl.h grp.h locale.h math.h pwd.h setjmp.h signal.h stdio.h stdlib.h string.h sys/socket.h sys/stat.h sys/times.h sys/resource.h sys/utsname.h sys/wait.h tar.h termios.h time.h unistd.h utime.h" rel_target_dir=$1 # All files in $src_dir_all (normally same as $rel_target_dir) are # processed. src_dir_all=$2 # In $src_dir_std (normally same as /usr/include), only the # "standard" ANSI/POSIX files listed in $std_files are processed. src_dir_std=$3 case $rel_target_dir in /* | [A-Za-z]:[\\/]*) abs_target_dir=$rel_target_dir ;; *) abs_target_dir=$original_dir/$rel_target_dir ;; esac # Determine whether this system has symbolic links. if ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then rm -f $rel_target_dir/ShouldNotExist LINKS=true elif ln -s X /tmp/ShouldNotExist 2>/dev/null; then rm -f /tmp/ShouldNotExist LINKS=true else LINKS=false fi if [ \! -d $abs_target_dir ] ; then echo $progname\: creating directory $rel_target_dir $mkinstalldirs $abs_target_dir fi echo $progname\: populating \`$rel_target_dir\' include_path="" if [ `echo $* | wc -w` != 0 ] ; then for rel_source_dir in $src_dir_all $src_dir_std; do case $rel_source_dir in /* | [A-Za-z]:[\\/]*) abs_source_dir=$rel_source_dir ;; *) abs_source_dir=$original_dir/$rel_source_dir ;; esac include_path="$include_path -I$abs_source_dir" done fi done_dirs="" subdirs_made="" echo "" >fixproto.list for code in ALL STD ; do subdirs="." case $code in ALL) rel_source_dir=$src_dir_all dirs="." levels=2 while $LINKS && test -n "$dirs" -a $levels -gt 0 do levels=`expr $levels - 1` newdirs= for d in $dirs ; do # Find all directories under $d, relative to $d, excluding $d itself. # Assume directory names ending in CC or containing ++ are # for C++, so skip those. subdirs="$subdirs "`cd $rel_source_dir/$d; find . -type d -print | \ sed -e '/^\.$/d' -e "s|^\./|${d}/|" -e 's|^\./||' \ -e '/CC$/d' -e '/[+][+]/d'` links= links=`cd $rel_source_dir; find $d/. -type l -print | \ sed -e "s|$d/./|$d/|" -e 's|^\./||'` for link in $links --dummy-- ; do test -d $rel_source_dir/$link/. && newdirs="$newdirs $link" done done dirs="$newdirs" subdirs="$subdirs $newdirs" done ;; STD) rel_source_dir=$src_dir_std ;; esac case $rel_source_dir in /* | [A-Za-z]:[\\/]*) abs_source_dir=$rel_source_dir ;; *) abs_source_dir=$original_dir/$rel_source_dir ;; esac if [ \! -d $abs_source_dir ] ; then echo $progname\: warning\: no such directory\: \`$rel_source_dir\' continue fi for rel_source_subdir in $subdirs; do abs_target_subdir=${abs_target_dir}/${rel_source_subdir} if [ \! -d $abs_target_subdir ] ; then if $mkinstalldirs $abs_target_subdir ; then subdirs_made="$abs_target_subdir $subdirs_made" fi fi # Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/". rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'` case $code in ALL) # The 'sed' is in case the *.h matches nothing, which yields "*.h" # which would then get re-globbed in the current directory. Sigh. rel_source_files=`cd ${abs_source_dir}/${rel_source_subdir}; echo *.h | sed -e 's|[*].h|NONE|'` ;; STD) files_to_check="$std_files" rel_source_files="" # Also process files #included by the $std_files. while [ -n "${files_to_check}" ] do new_files_to_check="" for file in $files_to_check ; do xxfile=`echo $file | sed -e 's|/\([^/\.][^/\.]*\)/\.\./|/|'` # Create the dir where this file will go when fixed. xxdir=`echo ./$file | sed -e 's|/[^/]*$||'` if [ \! -d $abs_target_subdir/$xxdir ] ; then if $mkinstalldirs $abs_target_subdir/$xxdir ; then subdirs_made="$abs_target_subdir/$xxdir $subdirs_made" fi fi # Just in case we have edited out a symbolic link if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then file=$xxfile fi case " $rel_source_files " in *" ${file} "*) # Already seen $file; nothing to do ;; *) if test -f $src_dir_std/$file ; then rel_dir=`echo $file | sed -n -e 's|^\(.*/\)[^/]*$|\1|p'` # For #include "foo.h", that might be either "foo.h" # or "${rel_dir}foo.h (or something bogus). new_files_to_check="$new_files_to_check "`sed -n \ -e 's@ @ @g' \ -e 's@^ *# *include *<\([^>]*\)>.*$@\1@p' -e \ 's@^ *# *include *\"\([^\"]*\)\".*$@\1 '$rel_dir'\1@p'\ <$src_dir_std/$file` rel_source_files="$rel_source_files $file" fi ;; esac done files_to_check="$new_files_to_check" done rel_source_files="$rel_source_files" ;; esac for filename in $rel_source_files ; do rel_source_file=${rel_source_prefix}${filename} abs_source_file=$abs_source_dir/$rel_source_file abs_target_file=$abs_target_dir/$rel_source_file if test "$filename" = 'NONE' ; then echo "(No *.h files in $abs_source_dir/$rel_source_subdir)" # If target file exists, check if was written while processing one # of the earlier source directories; if so ignore it. elif test -f $abs_target_file -a -n "$done_dirs" \ && grep "$rel_source_file" fixproto.list >/dev/null then true else $FIX_HEADER $rel_source_file $abs_source_file $abs_target_file ${DEFINES} $include_path if test $? != 0 ; then exit 1 ; fi echo "${rel_source_file}" >>fixproto.list fi done done done_dirs="$done_dir $rel_source_dir" done # This might be more cleanly moved into the main loop, by adding # a source directory at the end. FIXME! # All the headers we create define size_t and NULL. for rel_source_file in unistd.h stdlib.h string.h time.h ; do if grep "$rel_source_file" fixproto.list >/dev/null ; then : # It exists, we don't need to make it else echo Adding missing $rel_source_file rel_source_ident=`echo $rel_source_file | tr ./ __` cat >tmp.h < EOF # Insert special stuff for particular files here. case ${rel_source_file} in time.h) # If time.h doesn't exist, find out if sys/time.h does. if test -f $src_dir_std/sys/time.h \ || grep "sys/time.h" fixproto.list >/dev/null ; then # It does; include it and hope it has the needed declarations. # Some versions require sys/types.h. cat >>tmp.h < #include EOF else # It doesn't. Make up plausible definitions for time_t, clock_t. # Forward-declare struct tm. Hope nobody tries to use it. (Odds # are they won't.) cat >>tmp.h <>tmp.h </dev/null exit 0