1#!/bin/sh 2# 3# SYNOPSIS 4# fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD 5# 6# COPYRIGHT 7# Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc. 8# This file is part of GNU CC. 9# 10# GNU CC is free software; you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation; either version 2, or (at your option) 13# any later version. 14# 15# GNU CC is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with GNU CC; see the file COPYING. If not, write to 22# the Free Software Foundation, 59 Temple Place - Suite 330, 23# Boston, MA 02111-1307, USA. 24# 25# DESCRIPTION 26# Adjunct script for GNU CC to populate a directory with ANSI, 27# Posix.1, and C++ compatible header files. 28# 29# Each file found under SOURCE-DIR-ALL is analyzed and "fixed." 30# Only standard ANSI/POSIX files found under SOURCE-DIR-STD 31# are analyzed and "fixed." 32# The SOURCE-DIRs are searched in order; a file found 33# under multiple SOURCE-DIRs is only handled for the first one. 34# 35# STRATEGY 36# Each include file is fed through cpp, and the scan-decls program 37# parses it, and emits any found function declarations. 38# The fix-header program analyzes the scan-decls output, 39# together with the original include file, and writes a "fixed" 40# include file, if needed. 41# 42# The comment at the beginning of fix-header.c lists specifically 43# what kind of changes are made. 44# 45# NOTE 46# Some file space will be wasted, because the original header 47# files are copied. An earlier version just included the original 48# by "reference", using GNU cpp's #include_next mechanism. 49# This is currently not done, partly because #include_next is 50# fragile (susceptible to version incompatibilities, and depends 51# and GCC-specific features), and partly for performance reasons. 52# 53# AUTHORS 54# Ron Guilmette (rfg@netcom.com) (original idea and code) 55# Per Bothner (bothner@cygnus.com) (major re-write) 56 57dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'` 58progname=`echo "$0" | sed 's,.*/,,'` 59original_dir=`pwd` 60FIX_HEADER=${FIX_HEADER-$original_dir/fix-header} 61DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}" 62 63if mkdir -p . 2> /dev/null; then 64 # Great, mkdir accepts -p 65 mkinstalldirs="mkdir -p" 66else 67 # We expect mkinstalldirs to be passed in the environment. 68 # If it is not, assume it is in the directory that contains this script. 69 mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"} 70 if $mkinstalldirs . 2> /dev/null; then 71 : 72 else 73 # But, in case of failure, fallback to plain mkdir, and hope it works 74 mkinstalldirs=mkdir 75 fi 76fi 77 78if [ `echo $1 | wc -w` = 0 ] ; then 79 echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \] 80 exit 1 81fi 82 83std_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" 84 85rel_target_dir=$1 86# All files in $src_dir_all (normally same as $rel_target_dir) are 87# processed. 88src_dir_all=$2 89# In $src_dir_std (normally same as /usr/include), only the 90# "standard" ANSI/POSIX files listed in $std_files are processed. 91src_dir_std=$3 92 93if [ `expr $rel_target_dir : '\(.\)'` != '/' ] ; then 94 abs_target_dir=$original_dir/$rel_target_dir 95else 96 abs_target_dir=$rel_target_dir 97fi 98 99# Determine whether this system has symbolic links. 100if ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then 101 rm -f $rel_target_dir/ShouldNotExist 102 LINKS=true 103elif ln -s X /tmp/ShouldNotExist 2>/dev/null; then 104 rm -f /tmp/ShouldNotExist 105 LINKS=true 106else 107 LINKS=false 108fi 109 110if [ \! -d $abs_target_dir ] ; then 111 echo $progname\: creating directory $rel_target_dir 112 $mkinstalldirs $abs_target_dir 113fi 114 115echo $progname\: populating \`$rel_target_dir\' 116 117include_path="" 118 119if [ `echo $* | wc -w` != 0 ] ; then 120 for rel_source_dir in $src_dir_all $src_dir_std; do 121 if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then 122 abs_source_dir=$original_dir/$rel_source_dir 123 else 124 abs_source_dir=$rel_source_dir 125 fi 126 include_path="$include_path -I$abs_source_dir" 127 done 128fi 129 130required_stdlib_h="abort abs atexit atof atoi atol bsearch calloc exit free getenv labs malloc putenv qsort rand realloc srand strtod strtol strtoul system" 131# "div ldiv", - ignored because these depend on div_t, ldiv_t 132# ignore these: "mblen mbstowcs mbstowc wcstombs wctomb" 133# Left out getgroups, because SunOS4 has incompatible BSD and SVR4 versions. 134# Should perhaps also add NULL 135required_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" 136 137done_dirs="" 138subdirs_made="" 139echo "" >fixproto.list 140 141for code in ALL STD ; do 142 143 subdirs="." 144 145 case $code in 146 ALL) 147 rel_source_dir=$src_dir_all 148 149 dirs="." 150 levels=2 151 while $LINKS && test -n "$dirs" -a $levels -gt 0 152 do 153 levels=`expr $levels - 1` 154 newdirs= 155 for d in $dirs ; do 156 # Find all directories under $d, relative to $d, excluding $d itself. 157 # Assume directory names ending in CC or containing ++ are 158 # for C++, so skip those. 159 subdirs="$subdirs "`cd $rel_source_dir/$d; find . -type d -print | \ 160 sed -e '/^\.$/d' -e "s|^\./|${d}/|" -e 's|^\./||' \ 161 -e '/CC$/d' -e '/[+][+]/d'` 162 links= 163 links=`cd $rel_source_dir; find $d/. -type l -print | \ 164 sed -e "s|$d/./|$d/|" -e 's|^\./||'` 165 for link in $links --dummy-- ; do 166 test -d $rel_source_dir/$link/. && newdirs="$newdirs $link" 167 done 168 done 169 dirs="$newdirs" 170 subdirs="$subdirs $newdirs" 171 done 172 ;; 173 STD) 174 rel_source_dir=$src_dir_std 175 ;; 176 esac 177 178 if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then 179 abs_source_dir=$original_dir/$rel_source_dir 180 else 181 abs_source_dir=$rel_source_dir 182 fi 183 184 if [ \! -d $abs_source_dir ] ; then 185 echo $progname\: warning\: no such directory\: \`$rel_source_dir\' 186 continue 187 fi 188 189 for rel_source_subdir in $subdirs; do 190 191 abs_target_subdir=${abs_target_dir}/${rel_source_subdir} 192 if [ \! -d $abs_target_subdir ] ; then 193 if $mkinstalldirs $abs_target_subdir ; then 194 subdirs_made="$abs_target_subdir $subdirs_made" 195 fi 196 fi 197 # Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/". 198 rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'` 199 200 case $code in 201 ALL) 202 # The 'sed' is in case the *.h matches nothing, which yields "*.h" 203 # which would then get re-globbed in the current directory. Sigh. 204 rel_source_files=`cd ${abs_source_dir}/${rel_source_subdir}; echo *.h | sed -e 's|[*].h|NONE|'` 205 ;; 206 207 STD) 208 files_to_check="$std_files" 209 rel_source_files="" 210 211 # Also process files #included by the $std_files. 212 while [ -n "${files_to_check}" ] 213 do 214 new_files_to_check="" 215 for file in $files_to_check ; do 216 xxfile=`echo $file | sed -e 's|/\([^/\.][^/\.]*\)/\.\./|/|'` 217 # Create the dir where this file will go when fixed. 218 xxdir=`echo ./$file | sed -e 's|/[^/]*$||'` 219 if [ \! -d $abs_target_subdir/$xxdir ] ; then 220 if $mkinstalldirs $abs_target_subdir/$xxdir ; then 221 subdirs_made="$abs_target_subdir/$xxdir $subdirs_made" 222 fi 223 fi 224 # Just in case we have edited out a symbolic link 225 if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then 226 file=$xxfile 227 fi 228 case " $rel_source_files " in 229 *" ${file} "*) 230 # Already seen $file; nothing to do 231 ;; 232 *) 233 if test -f $src_dir_std/$file ; then 234 rel_dir=`echo $file | sed -n -e 's|^\(.*/\)[^/]*$|\1|p'` 235 # For #include "foo.h", that might be either "foo.h" 236 # or "${rel_dir}foo.h (or something bogus). 237 new_files_to_check="$new_files_to_check "`sed -n \ 238 -e 's@ @ @g' \ 239 -e 's@^ *# *include *<\([^>]*\)>.*$@\1@p' -e \ 240 's@^ *# *include *\"\([^\"]*\)\".*$@\1 '$rel_dir'\1@p'\ 241 <$src_dir_std/$file` 242 rel_source_files="$rel_source_files $file" 243 fi 244 ;; 245 esac 246 done 247 files_to_check="$new_files_to_check" 248 done 249 rel_source_files="$rel_source_files" 250 ;; 251 esac 252 253 for filename in $rel_source_files ; do 254 rel_source_file=${rel_source_prefix}${filename} 255 abs_source_file=$abs_source_dir/$rel_source_file 256 abs_target_file=$abs_target_dir/$rel_source_file 257 258 if test "$filename" = 'NONE' ; then 259 echo "(No *.h files in $abs_source_dir/$rel_source_subdir)" 260 # If target file exists, check if was written while processing one 261 # of the earlier source directories; if so ignore it. 262 elif test -f $abs_target_file -a -n "$done_dirs" \ 263 && grep "$rel_source_file" fixproto.list >/dev/null 264 then true 265 else 266 $FIX_HEADER $rel_source_file $abs_source_file $abs_target_file ${DEFINES} $include_path 267 echo "${rel_source_file}" >>fixproto.list 268 fi 269 done 270 done 271 done_dirs="$done_dir $rel_source_dir" 272done 273 274# This might be more cleanly moved into the main loop, by adding 275# a <dummy> source directory at the end. FIXME! 276for rel_source_file in unistd.h stdlib.h 277do 278 if grep "$rel_source_file" fixproto.list >/dev/null 279 then true 280 else 281 echo Adding missing $rel_source_file 282 rel_source_ident=`echo $rel_source_file | tr ./ __` 283 required_list=`eval echo '${required_'${rel_source_ident}'-}'` 284 cat >tmp.h <<EOF 285#ifndef __${rel_source_ident} 286#define __${rel_source_ident} 287EOF 288 if test $rel_source_file = stdlib.h 289 then 290 # Make sure it contains a definition of size_t. 291 cat >>tmp.h <<EOF 292 293#define __need_size_t 294#include <stddef.h> 295EOF 296 fi 297 cat >>tmp.h <<EOF 298 299#endif /* __${rel_source_ident} */ 300EOF 301 ${FIX_HEADER} $rel_source_file tmp.h $abs_target_dir/$rel_source_file ${DEFINES} $include_path 302 rm tmp.h 303 fi 304done 305 306# Remove any directories that we made that are still empty. 307rmdir $subdirs_made 2>/dev/null 308 309exit 0 310