118334Speter#!/bin/sh 218334Speter# 318334Speter# SYNOPSIS 418334Speter# fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD 518334Speter# 618334Speter# COPYRIGHT 7132718Skan# Copyright (C) 1993, 1994, 1997, 1998, 2002, 2003 8132718Skan# Free Software Foundation, Inc. 990075Sobrien# This file is part of GCC. 1018334Speter# 1190075Sobrien# GCC is free software; you can redistribute it and/or modify 1218334Speter# it under the terms of the GNU General Public License as published by 1318334Speter# the Free Software Foundation; either version 2, or (at your option) 1418334Speter# any later version. 1518334Speter# 1690075Sobrien# GCC is distributed in the hope that it will be useful, 1718334Speter# but WITHOUT ANY WARRANTY; without even the implied warranty of 1818334Speter# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1918334Speter# GNU General Public License for more details. 2018334Speter# 2118334Speter# You should have received a copy of the GNU General Public License 2290075Sobrien# along with GCC; see the file COPYING. If not, write to 23169689Skan# the Free Software Foundation, 51 Franklin Street, Fifth Floor, 24169689Skan# Boston, MA 02110-1301, USA. 2518334Speter# 2618334Speter# DESCRIPTION 2790075Sobrien# Adjunct script for GCC to populate a directory with ANSI, 2818334Speter# Posix.1, and C++ compatible header files. 2918334Speter# 3018334Speter# Each file found under SOURCE-DIR-ALL is analyzed and "fixed." 3118334Speter# Only standard ANSI/POSIX files found under SOURCE-DIR-STD 3218334Speter# are analyzed and "fixed." 3318334Speter# The SOURCE-DIRs are searched in order; a file found 3418334Speter# under multiple SOURCE-DIRs is only handled for the first one. 3518334Speter# 3618334Speter# STRATEGY 3718334Speter# Each include file is fed through cpp, and the scan-decls program 3818334Speter# parses it, and emits any found function declarations. 3918334Speter# The fix-header program analyzes the scan-decls output, 4018334Speter# together with the original include file, and writes a "fixed" 4118334Speter# include file, if needed. 4218334Speter# 4318334Speter# The comment at the beginning of fix-header.c lists specifically 4418334Speter# what kind of changes are made. 4518334Speter# 4618334Speter# NOTE 4718334Speter# Some file space will be wasted, because the original header 4818334Speter# files are copied. An earlier version just included the original 4918334Speter# by "reference", using GNU cpp's #include_next mechanism. 5018334Speter# This is currently not done, partly because #include_next is 5118334Speter# fragile (susceptible to version incompatibilities, and depends 5218334Speter# and GCC-specific features), and partly for performance reasons. 5318334Speter# 5418334Speter# AUTHORS 5518334Speter# Ron Guilmette (rfg@netcom.com) (original idea and code) 5618334Speter# Per Bothner (bothner@cygnus.com) (major re-write) 5718334Speter 5852284Sobriendirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'` 5952284Sobrienprogname=`echo "$0" | sed 's,.*/,,'` 60117395Skanoriginal_dir=`${PWDCMD-pwd}` 6118334SpeterFIX_HEADER=${FIX_HEADER-$original_dir/fix-header} 6218334SpeterDEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}" 6318334Speter 6452284Sobrienif mkdir -p . 2> /dev/null; then 6552284Sobrien # Great, mkdir accepts -p 6652284Sobrien mkinstalldirs="mkdir -p" 6752284Sobrienelse 6852284Sobrien # We expect mkinstalldirs to be passed in the environment. 6952284Sobrien # If it is not, assume it is in the directory that contains this script. 7052284Sobrien mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"} 7152284Sobrien if $mkinstalldirs . 2> /dev/null; then 7252284Sobrien : 7352284Sobrien else 7452284Sobrien # But, in case of failure, fallback to plain mkdir, and hope it works 7552284Sobrien mkinstalldirs=mkdir 7652284Sobrien fi 7752284Sobrienfi 7852284Sobrien 7918334Speterif [ `echo $1 | wc -w` = 0 ] ; then 8018334Speter echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \] 8118334Speter exit 1 8218334Speterfi 8318334Speter 8450397Sobrienstd_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" 8518334Speter 8618334Speterrel_target_dir=$1 8718334Speter# All files in $src_dir_all (normally same as $rel_target_dir) are 8818334Speter# processed. 8918334Spetersrc_dir_all=$2 9018334Speter# In $src_dir_std (normally same as /usr/include), only the 9118334Speter# "standard" ANSI/POSIX files listed in $std_files are processed. 9218334Spetersrc_dir_std=$3 9318334Speter 9490075Sobriencase $rel_target_dir in 9590075Sobrien /* | [A-Za-z]:[\\/]*) 9690075Sobrien abs_target_dir=$rel_target_dir 9790075Sobrien ;; 9890075Sobrien *) 9990075Sobrien abs_target_dir=$original_dir/$rel_target_dir 10090075Sobrien ;; 10190075Sobrienesac 10218334Speter 10318334Speter# Determine whether this system has symbolic links. 10418334Speterif ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then 10518334Speter rm -f $rel_target_dir/ShouldNotExist 10618334Speter LINKS=true 10718334Speterelif ln -s X /tmp/ShouldNotExist 2>/dev/null; then 10818334Speter rm -f /tmp/ShouldNotExist 10918334Speter LINKS=true 11018334Speterelse 11118334Speter LINKS=false 11218334Speterfi 11318334Speter 11418334Speterif [ \! -d $abs_target_dir ] ; then 11518334Speter echo $progname\: creating directory $rel_target_dir 11652284Sobrien $mkinstalldirs $abs_target_dir 11718334Speterfi 11818334Speter 11918334Speterecho $progname\: populating \`$rel_target_dir\' 12018334Speter 12118334Speterinclude_path="" 12218334Speter 12318334Speterif [ `echo $* | wc -w` != 0 ] ; then 12418334Speter for rel_source_dir in $src_dir_all $src_dir_std; do 12590075Sobrien case $rel_source_dir in 12690075Sobrien /* | [A-Za-z]:[\\/]*) 12790075Sobrien abs_source_dir=$rel_source_dir 12890075Sobrien ;; 12990075Sobrien *) 13090075Sobrien abs_source_dir=$original_dir/$rel_source_dir 13190075Sobrien ;; 13290075Sobrien esac 13318334Speter include_path="$include_path -I$abs_source_dir" 13418334Speter done 13518334Speterfi 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 17890075Sobrien case $rel_source_dir in 17990075Sobrien /* | [A-Za-z]:[\\/]*) 18090075Sobrien abs_source_dir=$rel_source_dir 18190075Sobrien ;; 18290075Sobrien *) 18390075Sobrien abs_source_dir=$original_dir/$rel_source_dir 18490075Sobrien ;; 18590075Sobrien esac 18618334Speter 18718334Speter if [ \! -d $abs_source_dir ] ; then 18818334Speter echo $progname\: warning\: no such directory\: \`$rel_source_dir\' 18918334Speter continue 19018334Speter fi 19118334Speter 19218334Speter for rel_source_subdir in $subdirs; do 19318334Speter 19418334Speter abs_target_subdir=${abs_target_dir}/${rel_source_subdir} 19518334Speter if [ \! -d $abs_target_subdir ] ; then 19652284Sobrien if $mkinstalldirs $abs_target_subdir ; then 19750397Sobrien subdirs_made="$abs_target_subdir $subdirs_made" 19850397Sobrien fi 19918334Speter fi 20018334Speter # Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/". 20118334Speter rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'` 20218334Speter 20318334Speter case $code in 20418334Speter ALL) 20518334Speter # The 'sed' is in case the *.h matches nothing, which yields "*.h" 20618334Speter # which would then get re-globbed in the current directory. Sigh. 20718334Speter rel_source_files=`cd ${abs_source_dir}/${rel_source_subdir}; echo *.h | sed -e 's|[*].h|NONE|'` 20818334Speter ;; 20918334Speter 21018334Speter STD) 21118334Speter files_to_check="$std_files" 21218334Speter rel_source_files="" 21318334Speter 21418334Speter # Also process files #included by the $std_files. 21518334Speter while [ -n "${files_to_check}" ] 21618334Speter do 21718334Speter new_files_to_check="" 21818334Speter for file in $files_to_check ; do 21918334Speter xxfile=`echo $file | sed -e 's|/\([^/\.][^/\.]*\)/\.\./|/|'` 22018334Speter # Create the dir where this file will go when fixed. 22118334Speter xxdir=`echo ./$file | sed -e 's|/[^/]*$||'` 22218334Speter if [ \! -d $abs_target_subdir/$xxdir ] ; then 22352284Sobrien if $mkinstalldirs $abs_target_subdir/$xxdir ; then 22450397Sobrien subdirs_made="$abs_target_subdir/$xxdir $subdirs_made" 22550397Sobrien fi 22618334Speter fi 22718334Speter # Just in case we have edited out a symbolic link 22818334Speter if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then 22918334Speter file=$xxfile 23018334Speter fi 23118334Speter case " $rel_source_files " in 23218334Speter *" ${file} "*) 23318334Speter # Already seen $file; nothing to do 23418334Speter ;; 23518334Speter *) 23618334Speter if test -f $src_dir_std/$file ; then 23718334Speter rel_dir=`echo $file | sed -n -e 's|^\(.*/\)[^/]*$|\1|p'` 23818334Speter # For #include "foo.h", that might be either "foo.h" 23918334Speter # or "${rel_dir}foo.h (or something bogus). 24018334Speter new_files_to_check="$new_files_to_check "`sed -n \ 24118334Speter -e 's@ @ @g' \ 24218334Speter -e 's@^ *# *include *<\([^>]*\)>.*$@\1@p' -e \ 24318334Speter 's@^ *# *include *\"\([^\"]*\)\".*$@\1 '$rel_dir'\1@p'\ 24418334Speter <$src_dir_std/$file` 24518334Speter rel_source_files="$rel_source_files $file" 24618334Speter fi 24718334Speter ;; 24818334Speter esac 24918334Speter done 25018334Speter files_to_check="$new_files_to_check" 25118334Speter done 25218334Speter rel_source_files="$rel_source_files" 25318334Speter ;; 25418334Speter esac 25518334Speter 25618334Speter for filename in $rel_source_files ; do 25718334Speter rel_source_file=${rel_source_prefix}${filename} 25818334Speter abs_source_file=$abs_source_dir/$rel_source_file 25918334Speter abs_target_file=$abs_target_dir/$rel_source_file 26018334Speter 26118334Speter if test "$filename" = 'NONE' ; then 26218334Speter echo "(No *.h files in $abs_source_dir/$rel_source_subdir)" 26318334Speter # If target file exists, check if was written while processing one 26418334Speter # of the earlier source directories; if so ignore it. 26518334Speter elif test -f $abs_target_file -a -n "$done_dirs" \ 26618334Speter && grep "$rel_source_file" fixproto.list >/dev/null 26718334Speter then true 26818334Speter else 26918334Speter $FIX_HEADER $rel_source_file $abs_source_file $abs_target_file ${DEFINES} $include_path 27090075Sobrien if test $? != 0 ; then exit 1 ; fi 27118334Speter echo "${rel_source_file}" >>fixproto.list 27218334Speter fi 27318334Speter done 27418334Speter done 27518334Speter done_dirs="$done_dir $rel_source_dir" 27618334Speterdone 27718334Speter 27818334Speter# This might be more cleanly moved into the main loop, by adding 27918334Speter# a <dummy> source directory at the end. FIXME! 280132718Skan 281132718Skan# All the headers we create define size_t and NULL. 282132718Skanfor rel_source_file in unistd.h stdlib.h string.h time.h ; do 283132718Skan if grep "$rel_source_file" fixproto.list >/dev/null ; then 284132718Skan : # It exists, we don't need to make it 28518334Speter else 28618334Speter echo Adding missing $rel_source_file 28718334Speter rel_source_ident=`echo $rel_source_file | tr ./ __` 28818334Speter cat >tmp.h <<EOF 289132718Skan/* Fake ${rel_source_file}, created by GCC. 290132718Skan The functions declared in this file do not necessarily exist in 291132718Skan your C library. */ 29250397Sobrien#ifndef __${rel_source_ident} 29350397Sobrien#define __${rel_source_ident} 29450397Sobrien 295132718Skan#define __need_NULL 29650397Sobrien#define __need_size_t 29750397Sobrien#include <stddef.h> 29850397SobrienEOF 299132718Skan # Insert special stuff for particular files here. 300132718Skan case ${rel_source_file} in 301132718Skan time.h) 302132718Skan # If time.h doesn't exist, find out if sys/time.h does. 303132718Skan if test -f $src_dir_std/sys/time.h \ 304132718Skan || grep "sys/time.h" fixproto.list >/dev/null ; then 305132718Skan # It does; include it and hope it has the needed declarations. 306132718Skan # Some versions require sys/types.h. 307132718Skan cat >>tmp.h <<EOF 308132718Skan 309132718Skan#include <sys/types.h> 310132718Skan#include <sys/time.h> 311132718SkanEOF 312132718Skan else 313132718Skan # It doesn't. Make up plausible definitions for time_t, clock_t. 314132718Skan # Forward-declare struct tm. Hope nobody tries to use it. (Odds 315132718Skan # are they won't.) 316132718Skan cat >>tmp.h <<EOF 317132718Skan 318132718Skantypedef long time_t; 319132718Skantypedef long clock_t; 320132718Skanstruct tm; 321132718SkanEOF 322132718Skan fi ;; 323132718Skan esac 32450397Sobrien cat >>tmp.h <<EOF 32550397Sobrien 32650397Sobrien#endif /* __${rel_source_ident} */ 32750397SobrienEOF 32818334Speter ${FIX_HEADER} $rel_source_file tmp.h $abs_target_dir/$rel_source_file ${DEFINES} $include_path 32990075Sobrien if test $? != 0 ; then exit 1 ; fi 330132718Skan if test -f $abs_target_dir/$rel_source_file ; then 33190075Sobrien rm tmp.h 33290075Sobrien else 33390075Sobrien mv tmp.h $abs_target_dir/$rel_source_file 33490075Sobrien fi 33518334Speter fi 33618334Speterdone 33750397Sobrien 33850397Sobrien# Remove any directories that we made that are still empty. 33950397Sobrienrmdir $subdirs_made 2>/dev/null 34050397Sobrien 34118334Speterexit 0 342