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, 2002, 2003 8# Free Software Foundation, Inc. 9# This file is part of GCC. 10# 11# GCC is free software; you can redistribute it and/or modify 12# it under the terms of the GNU General Public License as published by 13# the Free Software Foundation; either version 2, or (at your option) 14# any later version. 15# 16# GCC is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License for more details. 20# 21# You should have received a copy of the GNU General Public License 22# along with GCC; see the file COPYING. If not, write to 23# the Free Software Foundation, 51 Franklin Street, Fifth Floor, 24# Boston, MA 02110-1301, USA. 25# 26# DESCRIPTION 27# Adjunct script for GCC to populate a directory with ANSI, 28# Posix.1, and C++ compatible header files. 29# 30# Each file found under SOURCE-DIR-ALL is analyzed and "fixed." 31# Only standard ANSI/POSIX files found under SOURCE-DIR-STD 32# are analyzed and "fixed." 33# The SOURCE-DIRs are searched in order; a file found 34# under multiple SOURCE-DIRs is only handled for the first one. 35# 36# STRATEGY 37# Each include file is fed through cpp, and the scan-decls program 38# parses it, and emits any found function declarations. 39# The fix-header program analyzes the scan-decls output, 40# together with the original include file, and writes a "fixed" 41# include file, if needed. 42# 43# The comment at the beginning of fix-header.c lists specifically 44# what kind of changes are made. 45# 46# NOTE 47# Some file space will be wasted, because the original header 48# files are copied. An earlier version just included the original 49# by "reference", using GNU cpp's #include_next mechanism. 50# This is currently not done, partly because #include_next is 51# fragile (susceptible to version incompatibilities, and depends 52# and GCC-specific features), and partly for performance reasons. 53# 54# AUTHORS 55# Ron Guilmette (rfg@netcom.com) (original idea and code) 56# Per Bothner (bothner@cygnus.com) (major re-write) 57 58dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'` 59progname=`echo "$0" | sed 's,.*/,,'` 60original_dir=`${PWDCMD-pwd}` 61FIX_HEADER=${FIX_HEADER-$original_dir/fix-header} 62DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}" 63 64if mkdir -p . 2> /dev/null; then 65 # Great, mkdir accepts -p 66 mkinstalldirs="mkdir -p" 67else 68 # We expect mkinstalldirs to be passed in the environment. 69 # If it is not, assume it is in the directory that contains this script. 70 mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"} 71 if $mkinstalldirs . 2> /dev/null; then 72 : 73 else 74 # But, in case of failure, fallback to plain mkdir, and hope it works 75 mkinstalldirs=mkdir 76 fi 77fi 78 79if [ `echo $1 | wc -w` = 0 ] ; then 80 echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \] 81 exit 1 82fi 83 84std_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" 85 86rel_target_dir=$1 87# All files in $src_dir_all (normally same as $rel_target_dir) are 88# processed. 89src_dir_all=$2 90# In $src_dir_std (normally same as /usr/include), only the 91# "standard" ANSI/POSIX files listed in $std_files are processed. 92src_dir_std=$3 93 94case $rel_target_dir in 95 /* | [A-Za-z]:[\\/]*) 96 abs_target_dir=$rel_target_dir 97 ;; 98 *) 99 abs_target_dir=$original_dir/$rel_target_dir 100 ;; 101esac 102 103# Determine whether this system has symbolic links. 104if ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then 105 rm -f $rel_target_dir/ShouldNotExist 106 LINKS=true 107elif ln -s X /tmp/ShouldNotExist 2>/dev/null; then 108 rm -f /tmp/ShouldNotExist 109 LINKS=true 110else 111 LINKS=false 112fi 113 114if [ \! -d $abs_target_dir ] ; then 115 echo $progname\: creating directory $rel_target_dir 116 $mkinstalldirs $abs_target_dir 117fi 118 119echo $progname\: populating \`$rel_target_dir\' 120 121include_path="" 122 123if [ `echo $* | wc -w` != 0 ] ; then 124 for rel_source_dir in $src_dir_all $src_dir_std; do 125 case $rel_source_dir in 126 /* | [A-Za-z]:[\\/]*) 127 abs_source_dir=$rel_source_dir 128 ;; 129 *) 130 abs_source_dir=$original_dir/$rel_source_dir 131 ;; 132 esac 133 include_path="$include_path -I$abs_source_dir" 134 done 135fi 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 case $rel_source_dir in 179 /* | [A-Za-z]:[\\/]*) 180 abs_source_dir=$rel_source_dir 181 ;; 182 *) 183 abs_source_dir=$original_dir/$rel_source_dir 184 ;; 185 esac 186 187 if [ \! -d $abs_source_dir ] ; then 188 echo $progname\: warning\: no such directory\: \`$rel_source_dir\' 189 continue 190 fi 191 192 for rel_source_subdir in $subdirs; do 193 194 abs_target_subdir=${abs_target_dir}/${rel_source_subdir} 195 if [ \! -d $abs_target_subdir ] ; then 196 if $mkinstalldirs $abs_target_subdir ; then 197 subdirs_made="$abs_target_subdir $subdirs_made" 198 fi 199 fi 200 # Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/". 201 rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'` 202 203 case $code in 204 ALL) 205 # The 'sed' is in case the *.h matches nothing, which yields "*.h" 206 # which would then get re-globbed in the current directory. Sigh. 207 rel_source_files=`cd ${abs_source_dir}/${rel_source_subdir}; echo *.h | sed -e 's|[*].h|NONE|'` 208 ;; 209 210 STD) 211 files_to_check="$std_files" 212 rel_source_files="" 213 214 # Also process files #included by the $std_files. 215 while [ -n "${files_to_check}" ] 216 do 217 new_files_to_check="" 218 for file in $files_to_check ; do 219 xxfile=`echo $file | sed -e 's|/\([^/\.][^/\.]*\)/\.\./|/|'` 220 # Create the dir where this file will go when fixed. 221 xxdir=`echo ./$file | sed -e 's|/[^/]*$||'` 222 if [ \! -d $abs_target_subdir/$xxdir ] ; then 223 if $mkinstalldirs $abs_target_subdir/$xxdir ; then 224 subdirs_made="$abs_target_subdir/$xxdir $subdirs_made" 225 fi 226 fi 227 # Just in case we have edited out a symbolic link 228 if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then 229 file=$xxfile 230 fi 231 case " $rel_source_files " in 232 *" ${file} "*) 233 # Already seen $file; nothing to do 234 ;; 235 *) 236 if test -f $src_dir_std/$file ; then 237 rel_dir=`echo $file | sed -n -e 's|^\(.*/\)[^/]*$|\1|p'` 238 # For #include "foo.h", that might be either "foo.h" 239 # or "${rel_dir}foo.h (or something bogus). 240 new_files_to_check="$new_files_to_check "`sed -n \ 241 -e 's@ @ @g' \ 242 -e 's@^ *# *include *<\([^>]*\)>.*$@\1@p' -e \ 243 's@^ *# *include *\"\([^\"]*\)\".*$@\1 '$rel_dir'\1@p'\ 244 <$src_dir_std/$file` 245 rel_source_files="$rel_source_files $file" 246 fi 247 ;; 248 esac 249 done 250 files_to_check="$new_files_to_check" 251 done 252 rel_source_files="$rel_source_files" 253 ;; 254 esac 255 256 for filename in $rel_source_files ; do 257 rel_source_file=${rel_source_prefix}${filename} 258 abs_source_file=$abs_source_dir/$rel_source_file 259 abs_target_file=$abs_target_dir/$rel_source_file 260 261 if test "$filename" = 'NONE' ; then 262 echo "(No *.h files in $abs_source_dir/$rel_source_subdir)" 263 # If target file exists, check if was written while processing one 264 # of the earlier source directories; if so ignore it. 265 elif test -f $abs_target_file -a -n "$done_dirs" \ 266 && grep "$rel_source_file" fixproto.list >/dev/null 267 then true 268 else 269 $FIX_HEADER $rel_source_file $abs_source_file $abs_target_file ${DEFINES} $include_path 270 if test $? != 0 ; then exit 1 ; fi 271 echo "${rel_source_file}" >>fixproto.list 272 fi 273 done 274 done 275 done_dirs="$done_dir $rel_source_dir" 276done 277 278# This might be more cleanly moved into the main loop, by adding 279# a <dummy> source directory at the end. FIXME! 280 281# All the headers we create define size_t and NULL. 282for rel_source_file in unistd.h stdlib.h string.h time.h ; do 283 if grep "$rel_source_file" fixproto.list >/dev/null ; then 284 : # It exists, we don't need to make it 285 else 286 echo Adding missing $rel_source_file 287 rel_source_ident=`echo $rel_source_file | tr ./ __` 288 cat >tmp.h <<EOF 289/* Fake ${rel_source_file}, created by GCC. 290 The functions declared in this file do not necessarily exist in 291 your C library. */ 292#ifndef __${rel_source_ident} 293#define __${rel_source_ident} 294 295#define __need_NULL 296#define __need_size_t 297#include <stddef.h> 298EOF 299 # Insert special stuff for particular files here. 300 case ${rel_source_file} in 301 time.h) 302 # If time.h doesn't exist, find out if sys/time.h does. 303 if test -f $src_dir_std/sys/time.h \ 304 || grep "sys/time.h" fixproto.list >/dev/null ; then 305 # It does; include it and hope it has the needed declarations. 306 # Some versions require sys/types.h. 307 cat >>tmp.h <<EOF 308 309#include <sys/types.h> 310#include <sys/time.h> 311EOF 312 else 313 # It doesn't. Make up plausible definitions for time_t, clock_t. 314 # Forward-declare struct tm. Hope nobody tries to use it. (Odds 315 # are they won't.) 316 cat >>tmp.h <<EOF 317 318typedef long time_t; 319typedef long clock_t; 320struct tm; 321EOF 322 fi ;; 323 esac 324 cat >>tmp.h <<EOF 325 326#endif /* __${rel_source_ident} */ 327EOF 328 ${FIX_HEADER} $rel_source_file tmp.h $abs_target_dir/$rel_source_file ${DEFINES} $include_path 329 if test $? != 0 ; then exit 1 ; fi 330 if test -f $abs_target_dir/$rel_source_file ; then 331 rm tmp.h 332 else 333 mv tmp.h $abs_target_dir/$rel_source_file 334 fi 335 fi 336done 337 338# Remove any directories that we made that are still empty. 339rmdir $subdirs_made 2>/dev/null 340 341exit 0 342