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