OSDN Git Service

2007-04-16 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / fixproto
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
58 dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'`
59 progname=`echo "$0" | sed 's,.*/,,'`
60 original_dir=`${PWDCMD-pwd}`
61 FIX_HEADER=${FIX_HEADER-$original_dir/fix-header}
62 DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}"
63
64 if mkdir -p . 2> /dev/null; then
65   # Great, mkdir accepts -p
66   mkinstalldirs="mkdir -p"
67 else
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
77 fi
78
79 if [ `echo $1 | wc -w` = 0 ] ; then
80   echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \]
81   exit 1
82 fi
83
84 std_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
86 rel_target_dir=$1
87 # All files in $src_dir_all (normally same as $rel_target_dir) are
88 # processed.
89 src_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.
92 src_dir_std=$3
93
94 case $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      ;;
101 esac
102
103 # Determine whether this system has symbolic links.
104 if ln -s X $rel_target_dir/ShouldNotExist 2>/dev/null; then
105   rm -f $rel_target_dir/ShouldNotExist
106   LINKS=true
107 elif ln -s X /tmp/ShouldNotExist 2>/dev/null; then
108   rm -f /tmp/ShouldNotExist
109   LINKS=true
110 else
111   LINKS=false
112 fi
113
114 if [ \! -d $abs_target_dir ] ; then
115   echo $progname\: creating directory $rel_target_dir
116   $mkinstalldirs $abs_target_dir
117 fi
118
119 echo $progname\: populating \`$rel_target_dir\'
120
121 include_path=""
122
123 if [ `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
135 fi
136
137 done_dirs=""
138 subdirs_made=""
139 echo "" >fixproto.list
140
141 for 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"
276 done
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.
282 for 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>
298 EOF
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>
311 EOF
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
318 typedef long time_t;
319 typedef long clock_t;
320 struct tm;
321 EOF
322         fi ;;
323     esac
324     cat >>tmp.h <<EOF
325
326 #endif /* __${rel_source_ident} */
327 EOF
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
336 done
337
338 # Remove any directories that we made that are still empty.
339 rmdir $subdirs_made 2>/dev/null
340
341 exit 0