fixproto revision 52284
118334Speter#!/bin/sh
218334Speter#
318334Speter# SYNOPSIS
418334Speter#	fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD
518334Speter#
618334Speter# COPYRIGHT
752284Sobrien#	Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
818334Speter#	This file is part of GNU CC.
918334Speter#
1018334Speter#	GNU CC is free software; you can redistribute it and/or modify
1118334Speter#	it under the terms of the GNU General Public License as published by
1218334Speter#	the Free Software Foundation; either version 2, or (at your option)
1318334Speter#	any later version.
1418334Speter#
1518334Speter#	GNU CC is distributed in the hope that it will be useful,
1618334Speter#	but WITHOUT ANY WARRANTY; without even the implied warranty of
1718334Speter#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1818334Speter#	GNU General Public License for more details.
1918334Speter#
2018334Speter#	You should have received a copy of the GNU General Public License
2118334Speter#	along with GNU CC; see the file COPYING.  If not, write to
2218334Speter#	the Free Software Foundation, 59 Temple Place - Suite 330,
2318334Speter#	Boston, MA 02111-1307, USA.
2418334Speter#
2518334Speter# DESCRIPTION
2618334Speter#	Adjunct script for GNU CC to populate a directory with ANSI,
2718334Speter#	Posix.1, and C++ compatible header files.
2818334Speter#
2918334Speter#	Each file found under SOURCE-DIR-ALL is analyzed and "fixed."
3018334Speter#       Only standard ANSI/POSIX files found under SOURCE-DIR-STD
3118334Speter#       are analyzed and "fixed."
3218334Speter#	The SOURCE-DIRs are searched in order; a file found
3318334Speter#	under multiple SOURCE-DIRs is only handled for the first one.
3418334Speter#
3518334Speter# STRATEGY
3618334Speter#       Each include file is fed through cpp, and the scan-decls program
3718334Speter#	parses it, and emits any found function declarations.
3818334Speter#	The fix-header program analyzes the scan-decls output,
3918334Speter#	together with the original include file, and writes a "fixed"
4018334Speter#	include file, if needed.
4118334Speter#
4218334Speter#	The comment at the beginning of fix-header.c lists specifically
4318334Speter#	what kind of changes are made.
4418334Speter#
4518334Speter# NOTE
4618334Speter#	Some file space will be wasted, because the original header
4718334Speter#	files are copied.  An earlier version just included the original
4818334Speter#	by "reference", using GNU cpp's #include_next mechanism.
4918334Speter#	This is currently not done, partly because #include_next is
5018334Speter#	fragile (susceptible to version incompatibilities, and depends
5118334Speter#	and GCC-specific features), and partly for performance reasons.
5218334Speter#
5318334Speter# AUTHORS
5418334Speter#	Ron Guilmette (rfg@netcom.com) (original idea and code)
5518334Speter#	Per Bothner (bothner@cygnus.com) (major re-write)
5618334Speter
5752284Sobriendirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'`
5852284Sobrienprogname=`echo "$0" | sed 's,.*/,,'`
5918334Speteroriginal_dir=`pwd`
6018334SpeterFIX_HEADER=${FIX_HEADER-$original_dir/fix-header}
6118334SpeterDEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}"
6218334Speter
6352284Sobrienif mkdir -p . 2> /dev/null; then
6452284Sobrien  # Great, mkdir accepts -p
6552284Sobrien  mkinstalldirs="mkdir -p"
6652284Sobrienelse
6752284Sobrien  # We expect mkinstalldirs to be passed in the environment.
6852284Sobrien  # If it is not, assume it is in the directory that contains this script.
6952284Sobrien  mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"}
7052284Sobrien  if $mkinstalldirs . 2> /dev/null; then
7152284Sobrien    :
7252284Sobrien  else
7352284Sobrien    # But, in case of failure, fallback to plain mkdir, and hope it works
7452284Sobrien    mkinstalldirs=mkdir
7552284Sobrien  fi
7652284Sobrienfi
7752284Sobrien
7818334Speterif [ `echo $1 | wc -w` = 0 ] ; then
7918334Speter  echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \]
8018334Speter  exit 1
8118334Speterfi
8218334Speter
8350397Sobrienstd_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"
8418334Speter
8518334Speterrel_target_dir=$1
8618334Speter# All files in $src_dir_all (normally same as $rel_target_dir) are
8718334Speter# processed.
8818334Spetersrc_dir_all=$2
8918334Speter# In $src_dir_std (normally same as /usr/include), only the
9018334Speter# "standard" ANSI/POSIX files listed in $std_files are processed.
9118334Spetersrc_dir_std=$3
9218334Speter
9318334Speterif [ `expr $rel_target_dir : '\(.\)'` != '/' ] ; then
9418334Speter  abs_target_dir=$original_dir/$rel_target_dir
9518334Speterelse
9618334Speter  abs_target_dir=$rel_target_dir
9718334Speterfi
9818334Speter
9918334Speter# Determine whether this system has symbolic links.
10018334Speterif ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then
10118334Speter  rm -f $rel_target_dir/ShouldNotExist
10218334Speter  LINKS=true
10318334Speterelif ln -s X /tmp/ShouldNotExist 2>/dev/null; then
10418334Speter  rm -f /tmp/ShouldNotExist
10518334Speter  LINKS=true
10618334Speterelse
10718334Speter  LINKS=false
10818334Speterfi
10918334Speter
11018334Speterif [ \! -d $abs_target_dir ] ; then
11118334Speter  echo $progname\: creating directory $rel_target_dir
11252284Sobrien  $mkinstalldirs $abs_target_dir
11318334Speterfi
11418334Speter
11518334Speterecho $progname\: populating \`$rel_target_dir\'
11618334Speter
11718334Speterinclude_path=""
11818334Speter
11918334Speterif [ `echo $* | wc -w` != 0 ] ; then
12018334Speter  for rel_source_dir in $src_dir_all $src_dir_std; do
12118334Speter    if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then
12218334Speter      abs_source_dir=$original_dir/$rel_source_dir
12318334Speter    else
12418334Speter      abs_source_dir=$rel_source_dir
12518334Speter    fi
12618334Speter    include_path="$include_path -I$abs_source_dir"
12718334Speter  done
12818334Speterfi
12918334Speter
13018334Speterrequired_stdlib_h="abort abs atexit atof atoi atol bsearch calloc exit free getenv labs malloc putenv qsort rand realloc srand strtod strtol strtoul system"
13118334Speter# "div ldiv", - ignored because these depend on div_t, ldiv_t
13218334Speter# ignore these: "mblen mbstowcs mbstowc wcstombs wctomb"
13318334Speter# Left out getgroups, because SunOS4 has incompatible BSD and SVR4 versions.
13418334Speter# Should perhaps also add NULL
13518334Speterrequired_unistd_h="_exit access alarm chdir chown close ctermid cuserid dup dup2 execl execle execlp execv execve execvp fork fpathconf getcwd getegid geteuid getgid getlogin getopt getpgrp getpid getppid getuid isatty link lseek pathconf pause pipe read rmdir setgid setpgid setsid setuid sleep sysconf tcgetpgrp tcsetpgrp ttyname unlink write"
13618334Speter
13718334Speterdone_dirs=""
13850397Sobriensubdirs_made=""
13918334Speterecho "" >fixproto.list
14018334Speter
14118334Speterfor code in ALL STD ; do
14218334Speter
14318334Speter  subdirs="."
14418334Speter
14518334Speter  case $code in
14618334Speter    ALL)
14718334Speter      rel_source_dir=$src_dir_all
14818334Speter
14918334Speter      dirs="."
15018334Speter      levels=2
15118334Speter      while $LINKS && test -n "$dirs" -a $levels -gt 0
15218334Speter      do
15318334Speter        levels=`expr $levels - 1`
15418334Speter	newdirs=
15518334Speter	for d in $dirs ; do
15618334Speter	  # Find all directories under $d, relative to $d, excluding $d itself.
15718334Speter	  # Assume directory names ending in CC or containing ++ are
15818334Speter	  # for C++, so skip those.
15918334Speter	  subdirs="$subdirs "`cd $rel_source_dir/$d; find . -type d -print | \
16018334Speter	           sed -e '/^\.$/d' -e "s|^\./|${d}/|" -e 's|^\./||' \
16150397Sobrien		     -e '/CC$/d' -e '/[+][+]/d'`
16218334Speter	  links=
16318334Speter	  links=`cd $rel_source_dir; find $d/. -type l -print | \
16418334Speter		       sed -e "s|$d/./|$d/|" -e 's|^\./||'`
16518334Speter	  for link in $links --dummy-- ; do
16618334Speter	    test -d $rel_source_dir/$link/. && newdirs="$newdirs $link"
16718334Speter	  done
16818334Speter	done
16918334Speter	dirs="$newdirs"
17018334Speter	subdirs="$subdirs $newdirs"
17118334Speter      done
17218334Speter      ;;
17318334Speter    STD)
17418334Speter      rel_source_dir=$src_dir_std
17518334Speter      ;;
17618334Speter  esac
17718334Speter
17818334Speter  if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then
17918334Speter    abs_source_dir=$original_dir/$rel_source_dir
18018334Speter  else
18118334Speter    abs_source_dir=$rel_source_dir
18218334Speter  fi
18318334Speter
18418334Speter  if [ \! -d $abs_source_dir ] ; then
18518334Speter    echo $progname\: warning\: no such directory\: \`$rel_source_dir\'
18618334Speter    continue
18718334Speter  fi
18818334Speter
18918334Speter  for rel_source_subdir in $subdirs; do
19018334Speter
19118334Speter      abs_target_subdir=${abs_target_dir}/${rel_source_subdir}
19218334Speter      if [ \! -d $abs_target_subdir ] ; then
19352284Sobrien	if $mkinstalldirs $abs_target_subdir ; then
19450397Sobrien	  subdirs_made="$abs_target_subdir $subdirs_made"
19550397Sobrien	fi
19618334Speter      fi
19718334Speter      # Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/".
19818334Speter      rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'`
19918334Speter
20018334Speter      case $code in
20118334Speter	ALL)
20218334Speter	  # The 'sed' is in case the *.h matches nothing, which yields "*.h"
20318334Speter	  # which would then get re-globbed in the current directory.  Sigh.
20418334Speter	  rel_source_files=`cd ${abs_source_dir}/${rel_source_subdir}; echo *.h | sed -e 's|[*].h|NONE|'`
20518334Speter	  ;;
20618334Speter
20718334Speter	STD)
20818334Speter	  files_to_check="$std_files"
20918334Speter	  rel_source_files=""
21018334Speter
21118334Speter	  # Also process files #included by the $std_files.
21218334Speter	  while [ -n "${files_to_check}" ]
21318334Speter	  do
21418334Speter	    new_files_to_check=""
21518334Speter	    for file in $files_to_check ; do
21618334Speter	      xxfile=`echo $file | sed -e 's|/\([^/\.][^/\.]*\)/\.\./|/|'`
21718334Speter	      # Create the dir where this file will go when fixed.
21818334Speter	      xxdir=`echo ./$file | sed -e 's|/[^/]*$||'`
21918334Speter	      if [ \! -d $abs_target_subdir/$xxdir ] ; then
22052284Sobrien		if $mkinstalldirs $abs_target_subdir/$xxdir ; then
22150397Sobrien		  subdirs_made="$abs_target_subdir/$xxdir $subdirs_made"
22250397Sobrien		fi
22318334Speter	      fi
22418334Speter	      # Just in case we have edited out a symbolic link
22518334Speter	      if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then
22618334Speter		file=$xxfile
22718334Speter	      fi
22818334Speter	      case " $rel_source_files " in
22918334Speter	        *" ${file} "*)
23018334Speter		  # Already seen $file; nothing to do
23118334Speter		  ;;
23218334Speter		*)
23318334Speter		  if test -f $src_dir_std/$file ; then
23418334Speter		    rel_dir=`echo $file | sed -n -e 's|^\(.*/\)[^/]*$|\1|p'`
23518334Speter		    # For #include "foo.h", that might be either "foo.h"
23618334Speter		    # or "${rel_dir}foo.h (or something bogus).
23718334Speter	            new_files_to_check="$new_files_to_check "`sed -n \
23818334Speter			-e 's@	@ @g' \
23918334Speter		        -e 's@^ *# *include *<\([^>]*\)>.*$@\1@p' -e \
24018334Speter		        's@^ *# *include *\"\([^\"]*\)\".*$@\1 '$rel_dir'\1@p'\
24118334Speter			<$src_dir_std/$file`
24218334Speter	            rel_source_files="$rel_source_files $file"
24318334Speter		  fi
24418334Speter		  ;;
24518334Speter	      esac
24618334Speter	    done
24718334Speter	    files_to_check="$new_files_to_check"
24818334Speter	  done
24918334Speter	  rel_source_files="$rel_source_files"
25018334Speter	  ;;
25118334Speter      esac
25218334Speter
25318334Speter      for filename in $rel_source_files ; do
25418334Speter	rel_source_file=${rel_source_prefix}${filename}
25518334Speter	abs_source_file=$abs_source_dir/$rel_source_file
25618334Speter	abs_target_file=$abs_target_dir/$rel_source_file
25718334Speter
25818334Speter	if test "$filename" = 'NONE' ; then
25918334Speter	  echo "(No *.h files in $abs_source_dir/$rel_source_subdir)"
26018334Speter	# If target file exists, check if was written while processing one
26118334Speter	# of the earlier source directories;  if so ignore it.
26218334Speter	elif test -f $abs_target_file -a -n "$done_dirs" \
26318334Speter	  && grep "$rel_source_file" fixproto.list >/dev/null
26418334Speter	then true
26518334Speter	else
26618334Speter	  $FIX_HEADER $rel_source_file $abs_source_file $abs_target_file ${DEFINES} $include_path
26718334Speter	  echo "${rel_source_file}" >>fixproto.list
26818334Speter	fi
26918334Speter      done
27018334Speter    done
27118334Speter    done_dirs="$done_dir $rel_source_dir"
27218334Speterdone
27318334Speter
27418334Speter# This might be more cleanly moved into the main loop, by adding
27518334Speter# a <dummy> source directory at the end.  FIXME!
27618334Speterfor rel_source_file in unistd.h stdlib.h
27718334Speterdo
27818334Speter  if grep "$rel_source_file" fixproto.list >/dev/null
27918334Speter  then true
28018334Speter  else
28118334Speter    echo Adding missing $rel_source_file
28218334Speter    rel_source_ident=`echo $rel_source_file | tr ./ __`
28318334Speter    required_list=`eval echo '${required_'${rel_source_ident}'-}'`
28418334Speter    cat >tmp.h <<EOF
28550397Sobrien#ifndef __${rel_source_ident}
28650397Sobrien#define __${rel_source_ident}
28718334SpeterEOF
28850397Sobrien    if test $rel_source_file = stdlib.h
28950397Sobrien    then
29050397Sobrien      # Make sure it contains a definition of size_t.
29150397Sobrien      cat >>tmp.h <<EOF
29250397Sobrien
29350397Sobrien#define __need_size_t
29450397Sobrien#include <stddef.h>
29550397SobrienEOF
29650397Sobrien    fi
29750397Sobrien    cat >>tmp.h <<EOF
29850397Sobrien
29950397Sobrien#endif /* __${rel_source_ident} */
30050397SobrienEOF
30118334Speter    ${FIX_HEADER} $rel_source_file tmp.h $abs_target_dir/$rel_source_file ${DEFINES} $include_path
30218334Speter    rm tmp.h
30318334Speter  fi
30418334Speterdone
30550397Sobrien
30650397Sobrien# Remove any directories that we made that are still empty.
30750397Sobrienrmdir $subdirs_made 2>/dev/null
30850397Sobrien
30918334Speterexit 0
310