mirror of
https://review.haiku-os.org/buildtools
synced 2026-02-04 07:53:14 +01:00
- added files that didn't make it in during the patch-session.
git-svn-id: file:///srv/svn/repos/haiku/trunk/buildtools@9623 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
176
gcc/gcc/fixinc/check.tpl
Normal file
176
gcc/gcc/fixinc/check.tpl
Normal file
@@ -0,0 +1,176 @@
|
||||
[= autogen5 template sh=check.sh =]
|
||||
[=
|
||||
#
|
||||
# This file contanes the shell template to run tests on the fixes
|
||||
#
|
||||
=]#!/bin/sh
|
||||
|
||||
set -e
|
||||
TESTDIR=tests
|
||||
TESTBASE=`cd $1;${PWDCMD-pwd}`
|
||||
|
||||
[ -d ${TESTDIR} ] || mkdir ${TESTDIR}
|
||||
cd ${TESTDIR}
|
||||
TESTDIR=`${PWDCMD-pwd}`
|
||||
|
||||
TARGET_MACHINE='*'
|
||||
DESTDIR=`${PWDCMD-pwd}`/res
|
||||
SRCDIR=`${PWDCMD-pwd}`/inc
|
||||
FIND_BASE='.'
|
||||
VERBOSE=[=` echo ${VERBOSE-1} `=]
|
||||
INPUT=`${PWDCMD-pwd}`
|
||||
ORIGDIR=${INPUT}
|
||||
|
||||
export TARGET_MACHINE DESTDIR SRCDIR FIND_BASE VERBOSE INPUT ORIGDIR
|
||||
|
||||
rm -rf ${DESTDIR} ${SRCDIR}
|
||||
mkdir ${DESTDIR} ${SRCDIR}
|
||||
(
|
||||
[=
|
||||
(shellf
|
||||
"for f in %s
|
||||
do case $f in
|
||||
*/* ) echo $f | sed 's;/[^/]*$;;' ;;
|
||||
esac
|
||||
done | sort -u | \
|
||||
while read g
|
||||
do echo \" mkdir \\${SRCDIR}/$g || mkdir -p \\${SRCDIR}/$g || exit 1\"
|
||||
done" (join " " (stack "fix.files")) ) =]
|
||||
) 2> /dev/null[= # suppress 'No such file or directory' messages =]
|
||||
cd inc
|
||||
[=
|
||||
(define sfile "")
|
||||
(define HACK "")
|
||||
(define dfile "") =][=
|
||||
|
||||
FOR fix =][=
|
||||
|
||||
IF (> (count "test_text") 1) =][=
|
||||
(set! HACK (string-upcase! (get "hackname")))
|
||||
(set! sfile (if (exist? "files") (get "files[]") "testing.h"))
|
||||
(set! dfile (string-append
|
||||
(if (*==* sfile "/")
|
||||
(shellf "echo \"%s\"|sed 's,/[^/]*,/,'" sfile )
|
||||
"" )
|
||||
(string-tr! (get "hackname") "_A-Z" "-a-z")
|
||||
) ) =][=
|
||||
|
||||
FOR test_text (for-from 1) =]
|
||||
cat >> [=(. sfile)=] <<_HACK_EOF_
|
||||
|
||||
|
||||
#if defined( [=(. HACK)=]_CHECK_[=(for-index)=] )
|
||||
[=test_text=]
|
||||
#endif /* [=(. HACK)=]_CHECK_[=(for-index)=] */
|
||||
_HACK_EOF_
|
||||
echo [=(. sfile)=] | ../../fixincl
|
||||
mv -f [=(. sfile)=] [=(. dfile)=]-[=(for-index)=].h
|
||||
[ -f ${DESTDIR}/[=(. sfile)=] ] && [=#
|
||||
=]mv ${DESTDIR}/[=(. sfile)=] ${DESTDIR}/[=(. dfile)=]-[=(for-index)=].h[=
|
||||
|
||||
ENDFOR test_text =][=
|
||||
|
||||
ENDIF multi-test =][=
|
||||
|
||||
ENDFOR fix
|
||||
|
||||
=][=
|
||||
|
||||
FOR fix =][=
|
||||
(set! HACK (string-upcase! (get "hackname"))) =][=
|
||||
|
||||
IF (not (exist? "test_text")) =][=
|
||||
(if (not (exist? "replace"))
|
||||
(error (sprintf "include fix '%s' has no test text"
|
||||
(get "hackname") )) )
|
||||
=][=
|
||||
ELSE =]
|
||||
cat >> [=
|
||||
IF (exist? "files") =][=
|
||||
files[0] =][=
|
||||
ELSE =]testing.h[=
|
||||
ENDIF =] <<_HACK_EOF_
|
||||
|
||||
|
||||
#if defined( [=(. HACK)=]_CHECK )
|
||||
[=test_text=]
|
||||
#endif /* [=(. HACK)=]_CHECK */
|
||||
_HACK_EOF_
|
||||
[=ENDIF =][=
|
||||
|
||||
ENDFOR fix
|
||||
|
||||
=]
|
||||
|
||||
find . -type f | sed 's;^\./;;' | sort | ../../fixincl
|
||||
cd ${DESTDIR}
|
||||
|
||||
exitok=true
|
||||
|
||||
find * -type f -print > ${TESTDIR}/LIST
|
||||
|
||||
# Special hack for sys/types.h: the #define-d types for size_t,
|
||||
# ptrdiff_t and wchar_t are different for each port. Therefore,
|
||||
# strip off the defined-to type so that the test results are the
|
||||
# same for all platforms.
|
||||
#
|
||||
sed 's/\(#define __[A-Z_]*_TYPE__\).*/\1/' sys/types.h > XX
|
||||
mv -f XX sys/types.h
|
||||
|
||||
# The following subshell weirdness is for saving an exit
|
||||
# status from within a while loop that reads input. If you can
|
||||
# think of a cleaner way, suggest away, please...
|
||||
#
|
||||
exitok=`
|
||||
exec < ${TESTDIR}/LIST
|
||||
while read f
|
||||
do
|
||||
if [ ! -f ${TESTBASE}/$f ]
|
||||
then
|
||||
echo "Newly fixed header: $f" >&2
|
||||
exitok=false
|
||||
|
||||
elif cmp $f ${TESTBASE}/$f >&2
|
||||
then
|
||||
:
|
||||
|
||||
else
|
||||
${DIFF:-diff} -c $f ${TESTBASE}/$f >&2 || :
|
||||
exitok=false
|
||||
fi
|
||||
done
|
||||
echo $exitok`
|
||||
|
||||
cd $TESTBASE
|
||||
|
||||
find * -type f -print | \
|
||||
fgrep -v 'CVS/' > ${TESTDIR}/LIST
|
||||
|
||||
exitok=`
|
||||
exec < ${TESTDIR}/LIST
|
||||
while read f
|
||||
do
|
||||
if [ -s $f ] && [ ! -f ${DESTDIR}/$f ]
|
||||
then
|
||||
echo "Missing header fix: $f" >&2
|
||||
exitok=false
|
||||
fi
|
||||
done
|
||||
echo $exitok`
|
||||
|
||||
echo
|
||||
if $exitok
|
||||
then
|
||||
cd ${TESTDIR}
|
||||
rm -rf inc res LIST
|
||||
cd ..
|
||||
rmdir ${TESTDIR} > /dev/null 2>&1 || :
|
||||
echo All fixinclude tests pass >&2
|
||||
else
|
||||
echo There were fixinclude test FAILURES >&2
|
||||
fi
|
||||
$exitok[=
|
||||
|
||||
(if (defined? 'set-writable) (set-writable))
|
||||
|
||||
=]
|
||||
809
gcc/gcc/fixinc/fixfixes.c
Normal file
809
gcc/gcc/fixinc/fixfixes.c
Normal file
@@ -0,0 +1,809 @@
|
||||
|
||||
/*
|
||||
|
||||
Test to see if a particular fix should be applied to a header file.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
= = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
NOTE TO DEVELOPERS
|
||||
|
||||
The routines you write here must work closely with fixincl.c.
|
||||
|
||||
Here are the rules:
|
||||
|
||||
1. Every test procedure name must be suffixed with "_fix".
|
||||
These routines will be referenced from inclhack.def, sans the suffix.
|
||||
|
||||
2. Use the "FIX_PROC_HEAD()" macro _with_ the "_fix" suffix
|
||||
(I cannot use the ## magic from ANSI C) for defining your entry point.
|
||||
|
||||
3. Put your test name into the FIXUP_TABLE.
|
||||
|
||||
4. Do not read anything from stdin. It is closed.
|
||||
|
||||
5. Write to stderr only in the event of a reportable error
|
||||
In such an event, call "exit (EXIT_FAILURE)".
|
||||
|
||||
6. You have access to the fixDescList entry for the fix in question.
|
||||
This may be useful, for example, if there are interesting strings
|
||||
or pre-compiled regular expressions stored there.
|
||||
|
||||
= = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "fixlib.h"
|
||||
#define GTYPE_SE_CT 1
|
||||
|
||||
#ifdef SEPARATE_FIX_PROC
|
||||
#include "fixincl.x"
|
||||
#endif
|
||||
|
||||
void fatal (const char *s, ...)
|
||||
{
|
||||
fprintf (stderr, "%s: %s\n", s);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
tSCC zNeedsArg[] = "fixincl error: `%s' needs %s argument (c_fix_arg[%d])\n";
|
||||
|
||||
typedef void t_fix_proc (const char *, const char *, tFixDesc *) ;
|
||||
typedef struct {
|
||||
const char* fix_name;
|
||||
t_fix_proc* fix_proc;
|
||||
} fix_entry_t;
|
||||
|
||||
#define FIXUP_TABLE \
|
||||
_FT_( "char_macro_def", char_macro_def_fix ) \
|
||||
_FT_( "char_macro_use", char_macro_use_fix ) \
|
||||
_FT_( "format", format_fix ) \
|
||||
_FT_( "machine_name", machine_name_fix ) \
|
||||
_FT_( "wrap", wrap_fix ) \
|
||||
_FT_( "gnu_type", gnu_type_fix )
|
||||
|
||||
|
||||
#define FIX_PROC_HEAD( fix ) \
|
||||
static void fix (const char* filname ATTRIBUTE_UNUSED , \
|
||||
const char* text ATTRIBUTE_UNUSED , \
|
||||
tFixDesc* p_fixd ATTRIBUTE_UNUSED )
|
||||
|
||||
#ifdef NEED_PRINT_QUOTE
|
||||
/*
|
||||
* Skip over a quoted string. Single quote strings may
|
||||
* contain multiple characters if the first character is
|
||||
* a backslash. Especially a backslash followed by octal digits.
|
||||
* We are not doing a correctness syntax check here.
|
||||
*/
|
||||
static char*
|
||||
print_quote(char q, char* text )
|
||||
{
|
||||
fputc( q, stdout );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char ch = *(text++);
|
||||
fputc( ch, stdout );
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\\':
|
||||
if (*text == NUL)
|
||||
goto quote_done;
|
||||
|
||||
fputc( *(text++), stdout );
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
if (ch != q)
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case '\n':
|
||||
case NUL:
|
||||
goto quote_done;
|
||||
}
|
||||
} quote_done:;
|
||||
|
||||
return text;
|
||||
}
|
||||
#endif /* NEED_PRINT_QUOTE */
|
||||
|
||||
|
||||
/*
|
||||
* Emit the GNU standard type wrapped up in such a way that
|
||||
* this thing can be encountered countless times during a compile
|
||||
* and not cause even a warning.
|
||||
*/
|
||||
static const char*
|
||||
emit_gnu_type (const char* text, regmatch_t* rm )
|
||||
{
|
||||
char z_TYPE[ 64 ];
|
||||
char z_type[ 64 ];
|
||||
|
||||
fwrite (text, rm[0].rm_so, 1, stdout);
|
||||
|
||||
{
|
||||
const char* ps = text + rm[1].rm_so;
|
||||
const char* pe = text + rm[1].rm_eo;
|
||||
char* pd = z_type;
|
||||
char* pD = z_TYPE;
|
||||
|
||||
while (ps < pe)
|
||||
*(pD++) = TOUPPER( *(pd++) = *(ps++) );
|
||||
|
||||
*pD = *pd = NUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now print out the reformed typedef,
|
||||
* with a C++ guard for WCHAR
|
||||
*/
|
||||
{
|
||||
tSCC z_fmt[] = "\
|
||||
#if !defined(_GCC_%s_T)%s\n\
|
||||
#define _GCC_%s_T\n\
|
||||
typedef __%s_TYPE__ %s_t;\n\
|
||||
#endif\n";
|
||||
|
||||
const char *const pz_guard = (strcmp (z_type, "wchar") == 0)
|
||||
? " && ! defined(__cplusplus)" : "";
|
||||
|
||||
printf (z_fmt, z_TYPE, pz_guard, z_TYPE, z_TYPE, z_type);
|
||||
}
|
||||
|
||||
return text += rm[0].rm_eo;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy the `format' string to std out, replacing `%n' expressions
|
||||
* with the matched text from a regular expression evaluation.
|
||||
* Doubled '%' characters will be replaced with a single copy.
|
||||
* '%' characters in other contexts and all other characters are
|
||||
* copied out verbatim.
|
||||
*/
|
||||
static void
|
||||
format_write (tCC* format, tCC* text, regmatch_t av[] )
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = (unsigned)*(format++)) != NUL) {
|
||||
|
||||
if (c != '%')
|
||||
{
|
||||
putchar(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
c = (unsigned)*(format++);
|
||||
|
||||
/*
|
||||
* IF the character following a '%' is not a digit,
|
||||
* THEN we will always emit a '%' and we may or may
|
||||
* not emit the following character. We will end on
|
||||
* a NUL and we will emit only one of a pair of '%'.
|
||||
*/
|
||||
if (! ISDIGIT ( c ))
|
||||
{
|
||||
putchar( '%' );
|
||||
switch (c) {
|
||||
case NUL:
|
||||
return;
|
||||
case '%':
|
||||
break;
|
||||
default:
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit the matched subexpression numbered 'c'.
|
||||
* IF, of course, there was such a match...
|
||||
*/
|
||||
else {
|
||||
regmatch_t* pRM = av + (c - (unsigned)'0');
|
||||
size_t len;
|
||||
|
||||
if (pRM->rm_so < 0)
|
||||
continue;
|
||||
|
||||
len = pRM->rm_eo - pRM->rm_so;
|
||||
if (len > 0)
|
||||
fwrite(text + pRM->rm_so, len, 1, stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search for multiple copies of a regular expression. Each block
|
||||
* of matched text is replaced with the format string, as described
|
||||
* above in `format_write'.
|
||||
*/
|
||||
FIX_PROC_HEAD( format_fix )
|
||||
{
|
||||
tCC* pz_pat = p_fixd->patch_args[2];
|
||||
tCC* pz_fmt = p_fixd->patch_args[1];
|
||||
regex_t re;
|
||||
regmatch_t rm[10];
|
||||
IGNORE_ARG(filname);
|
||||
|
||||
/*
|
||||
* We must have a format
|
||||
*/
|
||||
if (pz_fmt == (tCC*)NULL)
|
||||
{
|
||||
fprintf( stderr, zNeedsArg, p_fixd->fix_name, "replacement format", 0 );
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* IF we don't have a search text, then go find the first
|
||||
* regular expression among the tests.
|
||||
*/
|
||||
if (pz_pat == (tCC*)NULL)
|
||||
{
|
||||
tTestDesc* pTD = p_fixd->p_test_desc;
|
||||
int ct = p_fixd->test_ct;
|
||||
for (;;)
|
||||
{
|
||||
if (ct-- <= 0)
|
||||
{
|
||||
fprintf( stderr, zNeedsArg, p_fixd->fix_name, "search text", 1 );
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
|
||||
if (pTD->type == TT_EGREP)
|
||||
{
|
||||
pz_pat = pTD->pz_test_text;
|
||||
break;
|
||||
}
|
||||
|
||||
pTD++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace every copy of the text we find
|
||||
*/
|
||||
compile_re (pz_pat, &re, 1, "format search-text", "format_fix" );
|
||||
while (xregexec (&re, text, 10, rm, 0) == 0)
|
||||
{
|
||||
fwrite( text, rm[0].rm_so, 1, stdout );
|
||||
format_write( pz_fmt, text, rm );
|
||||
text += rm[0].rm_eo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump out the rest of the file
|
||||
*/
|
||||
fputs (text, stdout);
|
||||
}
|
||||
|
||||
|
||||
/* Scan the input file for all occurrences of text like this:
|
||||
|
||||
#define TIOCCONS _IO(T, 12)
|
||||
|
||||
and change them to read like this:
|
||||
|
||||
#define TIOCCONS _IO('T', 12)
|
||||
|
||||
which is the required syntax per the C standard. (The definition of
|
||||
_IO also has to be tweaked - see below.) 'IO' is actually whatever you
|
||||
provide as the `c_fix_arg' argument. */
|
||||
|
||||
FIX_PROC_HEAD( char_macro_use_fix )
|
||||
{
|
||||
/* This regexp looks for a traditional-syntax #define (# in column 1)
|
||||
of an object-like macro. */
|
||||
static const char pat[] =
|
||||
"^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+";
|
||||
static regex_t re;
|
||||
|
||||
const char* str = p_fixd->patch_args[1];
|
||||
regmatch_t rm[1];
|
||||
const char *p, *limit;
|
||||
size_t len;
|
||||
IGNORE_ARG(filname);
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
|
||||
len = strlen (str);
|
||||
compile_re (pat, &re, 1, "macro pattern", "char_macro_use_fix");
|
||||
|
||||
for (p = text;
|
||||
xregexec (&re, p, 1, rm, 0) == 0;
|
||||
p = limit + 1)
|
||||
{
|
||||
/* p + rm[0].rm_eo is the first character of the macro replacement.
|
||||
Find the end of the macro replacement, and the STR we were
|
||||
sent to look for within the replacement. */
|
||||
p += rm[0].rm_eo;
|
||||
limit = p - 1;
|
||||
do
|
||||
{
|
||||
limit = strchr (limit + 1, '\n');
|
||||
if (!limit)
|
||||
goto done;
|
||||
}
|
||||
while (limit[-1] == '\\');
|
||||
|
||||
do
|
||||
{
|
||||
if (*p == str[0] && !strncmp (p+1, str+1, len-1))
|
||||
goto found;
|
||||
}
|
||||
while (++p < limit - len);
|
||||
/* Hit end of line. */
|
||||
continue;
|
||||
|
||||
found:
|
||||
/* Found STR on this line. If the macro needs fixing,
|
||||
the next few chars will be whitespace or uppercase,
|
||||
then an open paren, then a single letter. */
|
||||
while ((ISSPACE (*p) || ISUPPER (*p)) && p < limit) p++;
|
||||
if (*p++ != '(')
|
||||
continue;
|
||||
if (!ISALPHA (*p))
|
||||
continue;
|
||||
if (ISIDNUM (p[1]))
|
||||
continue;
|
||||
|
||||
/* Splat all preceding text into the output buffer,
|
||||
quote the character at p, then proceed. */
|
||||
fwrite (text, 1, p - text, stdout);
|
||||
putchar ('\'');
|
||||
putchar (*p);
|
||||
putchar ('\'');
|
||||
text = p + 1;
|
||||
}
|
||||
done:
|
||||
fputs (text, stdout);
|
||||
}
|
||||
|
||||
|
||||
/* Scan the input file for all occurrences of text like this:
|
||||
|
||||
#define xxxIOxx(x, y) (....'x'<<16....)
|
||||
|
||||
and change them to read like this:
|
||||
|
||||
#define xxxIOxx(x, y) (....x<<16....)
|
||||
|
||||
which is the required syntax per the C standard. (The uses of _IO
|
||||
also has to be tweaked - see above.) 'IO' is actually whatever
|
||||
you provide as the `c_fix_arg' argument. */
|
||||
FIX_PROC_HEAD( char_macro_def_fix )
|
||||
{
|
||||
/* This regexp looks for any traditional-syntax #define (# in column 1). */
|
||||
static const char pat[] =
|
||||
"^#[ \t]*define[ \t]+";
|
||||
static regex_t re;
|
||||
|
||||
const char* str = p_fixd->patch_args[1];
|
||||
regmatch_t rm[1];
|
||||
const char *p, *limit;
|
||||
char arg;
|
||||
size_t len;
|
||||
IGNORE_ARG(filname);
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
|
||||
len = strlen (str);
|
||||
compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
|
||||
|
||||
for (p = text;
|
||||
xregexec (&re, p, 1, rm, 0) == 0;
|
||||
p = limit + 1)
|
||||
{
|
||||
/* p + rm[0].rm_eo is the first character of the macro name.
|
||||
Find the end of the macro replacement, and the STR we were
|
||||
sent to look for within the name. */
|
||||
p += rm[0].rm_eo;
|
||||
limit = p - 1;
|
||||
do
|
||||
{
|
||||
limit = strchr (limit + 1, '\n');
|
||||
if (!limit)
|
||||
goto done;
|
||||
}
|
||||
while (limit[-1] == '\\');
|
||||
|
||||
do
|
||||
{
|
||||
if (*p == str[0] && !strncmp (p+1, str+1, len-1))
|
||||
goto found;
|
||||
p++;
|
||||
}
|
||||
while (ISIDNUM (*p));
|
||||
/* Hit end of macro name without finding the string. */
|
||||
continue;
|
||||
|
||||
found:
|
||||
/* Found STR in this macro name. If the macro needs fixing,
|
||||
there may be a few uppercase letters, then there will be an
|
||||
open paren with _no_ intervening whitespace, and then a
|
||||
single letter. */
|
||||
while (ISUPPER (*p) && p < limit) p++;
|
||||
if (*p++ != '(')
|
||||
continue;
|
||||
if (!ISALPHA (*p))
|
||||
continue;
|
||||
if (ISIDNUM (p[1]))
|
||||
continue;
|
||||
|
||||
/* The character at P is the one to look for in the following
|
||||
text. */
|
||||
arg = *p;
|
||||
p += 2;
|
||||
|
||||
while (p < limit)
|
||||
{
|
||||
if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
|
||||
{
|
||||
/* Remove the quotes from this use of ARG. */
|
||||
p--;
|
||||
fwrite (text, 1, p - text, stdout);
|
||||
putchar (arg);
|
||||
p += 3;
|
||||
text = p;
|
||||
}
|
||||
else
|
||||
p++;
|
||||
}
|
||||
}
|
||||
done:
|
||||
fputs (text, stdout);
|
||||
}
|
||||
|
||||
/* Fix for machine name #ifdefs that are not in the namespace reserved
|
||||
by the C standard. They won't be defined if compiling with -ansi,
|
||||
and the headers will break. We go to some trouble to only change
|
||||
#ifdefs where the macro is defined by GCC in non-ansi mode; this
|
||||
minimizes the number of headers touched. */
|
||||
|
||||
#define SCRATCHSZ 64 /* hopefully long enough */
|
||||
|
||||
FIX_PROC_HEAD( machine_name_fix )
|
||||
{
|
||||
#ifndef MN_NAME_PAT
|
||||
fputs( "The target machine has no needed machine name fixes\n", stderr );
|
||||
#else
|
||||
regmatch_t match[2];
|
||||
const char *line, *base, *limit, *p, *q;
|
||||
regex_t *label_re, *name_re;
|
||||
char scratch[SCRATCHSZ];
|
||||
size_t len;
|
||||
IGNORE_ARG(filname);
|
||||
IGNORE_ARG(p_fixd);
|
||||
|
||||
mn_get_regexps (&label_re, &name_re, "machine_name_fix");
|
||||
|
||||
scratch[0] = '_';
|
||||
scratch[1] = '_';
|
||||
|
||||
for (base = text;
|
||||
xregexec (label_re, base, 2, match, 0) == 0;
|
||||
base = limit)
|
||||
{
|
||||
base += match[0].rm_eo;
|
||||
/* We're looking at an #if or #ifdef. Scan forward for the
|
||||
next non-escaped newline. */
|
||||
line = limit = base;
|
||||
do
|
||||
{
|
||||
limit++;
|
||||
limit = strchr (limit, '\n');
|
||||
if (!limit)
|
||||
goto done;
|
||||
}
|
||||
while (limit[-1] == '\\');
|
||||
|
||||
/* If the 'name_pat' matches in between base and limit, we have
|
||||
a bogon. It is not worth the hassle of excluding comments
|
||||
because comments on #if/#ifdef lines are rare, and strings on
|
||||
such lines are illegal.
|
||||
|
||||
REG_NOTBOL means 'base' is not at the beginning of a line, which
|
||||
shouldn't matter since the name_re has no ^ anchor, but let's
|
||||
be accurate anyway. */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
again:
|
||||
if (base == limit)
|
||||
break;
|
||||
|
||||
if (xregexec (name_re, base, 1, match, REG_NOTBOL))
|
||||
goto done; /* No remaining match in this file */
|
||||
|
||||
/* Match; is it on the line? */
|
||||
if (match[0].rm_eo > limit - base)
|
||||
break;
|
||||
|
||||
p = base + match[0].rm_so;
|
||||
base += match[0].rm_eo;
|
||||
|
||||
/* One more test: if on the same line we have the same string
|
||||
with the appropriate underscores, then leave it alone.
|
||||
We want exactly two leading and trailing underscores. */
|
||||
if (*p == '_')
|
||||
{
|
||||
len = base - p - ((*base == '_') ? 2 : 1);
|
||||
q = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = base - p - ((*base == '_') ? 1 : 0);
|
||||
q = p;
|
||||
}
|
||||
if (len + 4 > SCRATCHSZ)
|
||||
abort ();
|
||||
memcpy (&scratch[2], q, len);
|
||||
len += 2;
|
||||
scratch[len++] = '_';
|
||||
scratch[len++] = '_';
|
||||
|
||||
for (q = line; q <= limit - len; q++)
|
||||
if (*q == '_' && !strncmp (q, scratch, len))
|
||||
goto again;
|
||||
|
||||
fwrite (text, 1, p - text, stdout);
|
||||
fwrite (scratch, 1, len, stdout);
|
||||
|
||||
text = base;
|
||||
}
|
||||
}
|
||||
done:
|
||||
#endif
|
||||
fputs (text, stdout);
|
||||
}
|
||||
|
||||
|
||||
FIX_PROC_HEAD( wrap_fix )
|
||||
{
|
||||
tSCC z_no_wrap_pat[] = "^#if.*__need_";
|
||||
static regex_t no_wrapping_re; /* assume zeroed data */
|
||||
|
||||
tCC* pz_name = NULL;
|
||||
|
||||
if (no_wrapping_re.allocated == 0)
|
||||
compile_re( z_no_wrap_pat, &no_wrapping_re, 0, "no-wrap pattern",
|
||||
"wrap-fix" );
|
||||
|
||||
/*
|
||||
* IF we do *not* match the no-wrap re, then we have a double negative.
|
||||
* A double negative means YES.
|
||||
*/
|
||||
if (xregexec( &no_wrapping_re, text, 0, NULL, 0 ) != 0)
|
||||
{
|
||||
/*
|
||||
* A single file can get wrapped more than once by different fixes.
|
||||
* A single fix can wrap multiple files. Therefore, guard with
|
||||
* *both* the fix name and the file name.
|
||||
*/
|
||||
size_t ln = strlen( filname ) + strlen( p_fixd->fix_name ) + 14;
|
||||
char* pz = xmalloc( ln );
|
||||
pz_name = pz;
|
||||
sprintf( pz, "FIXINC_WRAP_%s-%s", filname, p_fixd->fix_name );
|
||||
|
||||
for (pz += 12; 1; pz++) {
|
||||
char ch = *pz;
|
||||
|
||||
if (ch == NUL)
|
||||
break;
|
||||
|
||||
if (! ISALNUM( ch )) {
|
||||
*pz = '_';
|
||||
}
|
||||
else {
|
||||
*pz = TOUPPER( ch );
|
||||
}
|
||||
}
|
||||
|
||||
printf( "#ifndef %s\n", pz_name );
|
||||
printf( "#define %s 1\n\n", pz_name );
|
||||
}
|
||||
|
||||
if (p_fixd->patch_args[1] == (tCC*)NULL)
|
||||
fputs( text, stdout );
|
||||
|
||||
else {
|
||||
fputs( p_fixd->patch_args[1], stdout );
|
||||
fputs( text, stdout );
|
||||
if (p_fixd->patch_args[2] != (tCC*)NULL)
|
||||
fputs( p_fixd->patch_args[2], stdout );
|
||||
}
|
||||
|
||||
if (pz_name != NULL) {
|
||||
printf( "\n#endif /* %s */\n", pz_name );
|
||||
free( (void*)pz_name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search for multiple copies of a regular expression. Each block
|
||||
* of matched text is replaced with the format string, as described
|
||||
* above in `format_write'.
|
||||
*/
|
||||
FIX_PROC_HEAD( gnu_type_fix )
|
||||
{
|
||||
const char* pz_pat;
|
||||
regex_t re;
|
||||
regmatch_t rm[GTYPE_SE_CT+1];
|
||||
IGNORE_ARG(filname);
|
||||
|
||||
{
|
||||
tTestDesc* pTD = p_fixd->p_test_desc;
|
||||
int ct = p_fixd->test_ct;
|
||||
for (;;)
|
||||
{
|
||||
if (ct-- <= 0)
|
||||
{
|
||||
fprintf (stderr, zNeedsArg, p_fixd->fix_name, "search text", 1);
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
|
||||
if (pTD->type == TT_EGREP)
|
||||
{
|
||||
pz_pat = pTD->pz_test_text;
|
||||
break;
|
||||
}
|
||||
|
||||
pTD++;
|
||||
}
|
||||
}
|
||||
|
||||
compile_re (pz_pat, &re, 1, "gnu type typedef", "gnu_type_fix");
|
||||
|
||||
while (xregexec (&re, text, GTYPE_SE_CT+1, rm, 0) == 0)
|
||||
{
|
||||
text = emit_gnu_type (text, rm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump out the rest of the file
|
||||
*/
|
||||
fputs (text, stdout);
|
||||
}
|
||||
|
||||
|
||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
test for fix selector
|
||||
|
||||
THIS IS THE ONLY EXPORTED ROUTINE
|
||||
|
||||
*/
|
||||
void
|
||||
apply_fix( tFixDesc* p_fixd, tCC* filname )
|
||||
{
|
||||
#define _FT_(n,p) { n, p },
|
||||
static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
|
||||
#undef _FT_
|
||||
#define FIX_TABLE_CT (ARRAY_SIZE (fix_table)-1)
|
||||
|
||||
tCC* fixname = p_fixd->patch_args[0];
|
||||
char* buf;
|
||||
int ct = FIX_TABLE_CT;
|
||||
fix_entry_t* pfe = fix_table;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (strcmp (pfe->fix_name, fixname) == 0)
|
||||
break;
|
||||
if (--ct <= 0)
|
||||
{
|
||||
fprintf (stderr, "fixincl error: the `%s' fix is unknown\n",
|
||||
fixname );
|
||||
exit (EXIT_BROKEN);
|
||||
}
|
||||
pfe++;
|
||||
}
|
||||
|
||||
buf = load_file_data (stdin);
|
||||
(*pfe->fix_proc)( filname, buf, p_fixd );
|
||||
}
|
||||
|
||||
#ifdef SEPARATE_FIX_PROC
|
||||
tSCC z_usage[] =
|
||||
"USAGE: applyfix <fix-name> <file-to-fix> <file-source> <file-destination>\n";
|
||||
tSCC z_reopen[] =
|
||||
"FS error %d (%s) reopening %s as std%s\n";
|
||||
|
||||
int
|
||||
main( int argc, char** argv )
|
||||
{
|
||||
tFixDesc* pFix;
|
||||
char* pz_tmptmp;
|
||||
char* pz_tmp_base;
|
||||
char* pz_tmp_dot;
|
||||
|
||||
if (argc != 5)
|
||||
{
|
||||
usage_failure:
|
||||
fputs (z_usage, stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
{
|
||||
char* pz = argv[1];
|
||||
long idx;
|
||||
|
||||
if (! ISDIGIT ( *pz ))
|
||||
goto usage_failure;
|
||||
|
||||
idx = strtol (pz, &pz, 10);
|
||||
if ((*pz != NUL) || ((unsigned)idx >= FIX_COUNT))
|
||||
goto usage_failure;
|
||||
pFix = fixDescList + idx;
|
||||
}
|
||||
|
||||
if (freopen (argv[3], "r", stdin) != stdin)
|
||||
{
|
||||
fprintf (stderr, z_reopen, errno, strerror( errno ), argv[3], "in");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pz_tmptmp = xmalloc (strlen (argv[4]) + 5);
|
||||
strcpy( pz_tmptmp, argv[4] );
|
||||
|
||||
/* Don't lose because "12345678" and "12345678X" map to the same
|
||||
file under DOS restricted 8+3 file namespace. Note that DOS
|
||||
doesn't allow more than one dot in the trunk of a file name. */
|
||||
pz_tmp_base = basename( pz_tmptmp );
|
||||
pz_tmp_dot = strchr( pz_tmp_base, '.' );
|
||||
if (pathconf( pz_tmptmp, _PC_NAME_MAX ) <= 12 /* is this DOS or Windows9X? */
|
||||
&& pz_tmp_dot != (char*)NULL)
|
||||
strcpy (pz_tmp_dot+1, "X"); /* nuke the original extension */
|
||||
else
|
||||
strcat (pz_tmptmp, ".X");
|
||||
if (freopen (pz_tmptmp, "w", stdout) != stdout)
|
||||
{
|
||||
fprintf (stderr, z_reopen, errno, strerror( errno ), pz_tmptmp, "out");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
apply_fix (pFix, argv[1]);
|
||||
fclose (stdout);
|
||||
fclose (stdin);
|
||||
unlink (argv[4]);
|
||||
if (rename (pz_tmptmp, argv[4]) != 0)
|
||||
{
|
||||
fprintf (stderr, "error %d (%s) renaming %s to %s\n", errno,
|
||||
strerror( errno ), pz_tmptmp, argv[4]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
283
gcc/gcc/fixinc/fixlib.c
Normal file
283
gcc/gcc/fixinc/fixlib.c
Normal file
@@ -0,0 +1,283 @@
|
||||
|
||||
/* Install modified versions of certain ANSI-incompatible system header
|
||||
files which are fixed to work correctly with ANSI C and placed in a
|
||||
directory that GCC will search.
|
||||
|
||||
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "fixlib.h"
|
||||
|
||||
/* * * * * * * * * * * * *
|
||||
|
||||
load_file_data loads all the contents of a file into malloc-ed memory.
|
||||
Its argument is the file pointer of the file to read in; the returned
|
||||
result is the NUL terminated contents of the file. The file
|
||||
is presumed to be an ASCII text file containing no NULs. */
|
||||
|
||||
char *
|
||||
load_file_data (FILE* fp)
|
||||
{
|
||||
char *pz_data = (char*)NULL;
|
||||
int space_left = -1; /* allow for terminating NUL */
|
||||
size_t space_used = 0;
|
||||
|
||||
if (fp == (FILE*)NULL)
|
||||
return pz_data;
|
||||
|
||||
do
|
||||
{
|
||||
size_t size_read;
|
||||
|
||||
if (space_left < 1024)
|
||||
{
|
||||
space_left += 4096;
|
||||
pz_data = xrealloc (pz_data, space_left + space_used + 1 );
|
||||
}
|
||||
size_read = fread (pz_data + space_used, 1, space_left, fp);
|
||||
|
||||
if (size_read == 0)
|
||||
{
|
||||
if (feof (fp))
|
||||
break;
|
||||
|
||||
if (ferror (fp))
|
||||
{
|
||||
int err = errno;
|
||||
if (err != EISDIR)
|
||||
fprintf (stderr, "error %d (%s) reading input\n", err,
|
||||
xstrerror (err));
|
||||
free ((void *) pz_data);
|
||||
return (char *) NULL;
|
||||
}
|
||||
}
|
||||
|
||||
space_left -= size_read;
|
||||
space_used += size_read;
|
||||
} while (! feof (fp));
|
||||
|
||||
pz_data = xrealloc (pz_data, space_used+1 );
|
||||
pz_data[ space_used ] = NUL;
|
||||
|
||||
return pz_data;
|
||||
}
|
||||
|
||||
#ifdef IS_CXX_HEADER_NEEDED
|
||||
t_bool
|
||||
is_cxx_header (tCC* fname, tCC* text)
|
||||
{
|
||||
/* First, check to see if the file is in a C++ directory */
|
||||
for (;;)
|
||||
{
|
||||
switch (*(fname++))
|
||||
{
|
||||
case 'C': /* check for "CC/" */
|
||||
if ((fname[0] == 'C') && (fname[1] == '/'))
|
||||
return BOOL_TRUE;
|
||||
break;
|
||||
|
||||
case 'x': /* check for "xx/" */
|
||||
if ((fname[0] == 'x') && (fname[1] == '/'))
|
||||
return BOOL_TRUE;
|
||||
break;
|
||||
|
||||
case '+': /* check for "++" */
|
||||
if (fname[0] == '+')
|
||||
return BOOL_TRUE;
|
||||
break;
|
||||
|
||||
case NUL:
|
||||
goto not_cxx_name;
|
||||
}
|
||||
} not_cxx_name:;
|
||||
|
||||
/* Or it might contain one of several phrases which indicate C++ code.
|
||||
Currently recognized are:
|
||||
extern "C++"
|
||||
-*- (Mode: )? C++ -*- (emacs mode marker)
|
||||
template <
|
||||
*/
|
||||
{
|
||||
tSCC cxxpat[] = "\
|
||||
extern[ \t]*\"C\\+\\+\"|\
|
||||
-\\*-[ \t]*([mM]ode:[ \t]*)?[cC]\\+\\+[; \t]*-\\*-|\
|
||||
template[ \t]*<|\
|
||||
^[ \t]*class[ \t]|\
|
||||
(public|private|protected):|\
|
||||
^[ \t]*#[ \t]*pragma[ \t]+(interface|implementation)\
|
||||
";
|
||||
static regex_t cxxre;
|
||||
static int compiled;
|
||||
|
||||
if (!compiled)
|
||||
compile_re (cxxpat, &cxxre, 0, "contents check", "is_cxx_header");
|
||||
|
||||
if (xregexec (&cxxre, text, 0, 0, 0) == 0)
|
||||
return BOOL_TRUE;
|
||||
}
|
||||
|
||||
return BOOL_FALSE;
|
||||
}
|
||||
#endif /* CXX_TYPE_NEEDED */
|
||||
|
||||
#ifdef SKIP_QUOTE_NEEDED
|
||||
/*
|
||||
* Skip over a quoted string. Single quote strings may
|
||||
* contain multiple characters if the first character is
|
||||
* a backslash. Especially a backslash followed by octal digits.
|
||||
* We are not doing a correctness syntax check here.
|
||||
*/
|
||||
tCC*
|
||||
skip_quote(char q, char* text )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char ch = *(text++);
|
||||
switch (ch)
|
||||
{
|
||||
case '\\':
|
||||
text++; /* skip over whatever character follows */
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
if (ch != q)
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case '\n':
|
||||
case NUL:
|
||||
goto skip_done;
|
||||
}
|
||||
} skip_done:;
|
||||
|
||||
return text;
|
||||
}
|
||||
#endif /* SKIP_QUOTE_NEEDED */
|
||||
|
||||
/* * * * * * * * * * * * *
|
||||
|
||||
Compile one regular expression pattern for later use. PAT contains
|
||||
the pattern, RE points to a regex_t structure (which should have
|
||||
been bzeroed). MATCH is 1 if we need to know where the regex
|
||||
matched, 0 if not. If xregcomp fails, prints an error message and
|
||||
aborts; E1 and E2 are strings to shove into the error message.
|
||||
|
||||
The patterns we search for are all egrep patterns.
|
||||
REG_EXTENDED|REG_NEWLINE produces identical regex syntax/semantics
|
||||
to egrep (verified from 4.4BSD Programmer's Reference Manual). */
|
||||
void
|
||||
compile_re( tCC* pat, regex_t* re, int match, tCC* e1, tCC* e2 )
|
||||
{
|
||||
tSCC z_bad_comp[] = "fixincl ERROR: cannot compile %s regex for %s\n\
|
||||
\texpr = `%s'\n\terror %s\n";
|
||||
int flags, err;
|
||||
|
||||
flags = (match ? REG_EXTENDED|REG_NEWLINE
|
||||
: REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
|
||||
err = xregcomp (re, pat, flags);
|
||||
|
||||
if (err)
|
||||
{
|
||||
char rerrbuf[1024];
|
||||
regerror (err, re, rerrbuf, 1024);
|
||||
fprintf (stderr, z_bad_comp, e1, e2, pat, rerrbuf);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * *
|
||||
|
||||
Helper routine and data for the machine_name test and fix.
|
||||
machname.h is created by black magic in the Makefile. */
|
||||
|
||||
#ifdef MN_NAME_PAT
|
||||
|
||||
tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+";
|
||||
static regex_t mn_label_re;
|
||||
|
||||
tSCC mn_name_pat[] = MN_NAME_PAT;
|
||||
static regex_t mn_name_re;
|
||||
|
||||
static int mn_compiled = 0;
|
||||
|
||||
void
|
||||
mn_get_regexps(regex_t** label_re, regex_t** name_re, tCC* who )
|
||||
{
|
||||
if (! mn_compiled)
|
||||
{
|
||||
compile_re (mn_label_pat, &mn_label_re, 1, "label pattern", who);
|
||||
compile_re (mn_name_pat, &mn_name_re, 1, "name pattern", who);
|
||||
mn_compiled++;
|
||||
}
|
||||
*label_re = &mn_label_re;
|
||||
*name_re = &mn_name_re;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SEPARATE_FIX_PROC
|
||||
|
||||
char*
|
||||
make_raw_shell_str( char* pz_d, tCC* pz_s, size_t smax )
|
||||
{
|
||||
tSCC zQ[] = "'\\''";
|
||||
size_t dtaSize;
|
||||
char* pz_d_start = pz_d;
|
||||
|
||||
smax--; /* adjust for trailing NUL */
|
||||
|
||||
dtaSize = strlen( pz_s ) + 3;
|
||||
|
||||
{
|
||||
const char* pz = pz_s - 1;
|
||||
|
||||
for (;;) {
|
||||
pz = strchr( pz+1, '\'' );
|
||||
if (pz == (char*)NULL)
|
||||
break;
|
||||
dtaSize += sizeof( zQ )-1;
|
||||
}
|
||||
}
|
||||
if (dtaSize > smax)
|
||||
return (char*)NULL;
|
||||
|
||||
*(pz_d++) = '\'';
|
||||
|
||||
for (;;) {
|
||||
if (pz_d - pz_d_start >= smax)
|
||||
return (char*)NULL;
|
||||
switch (*(pz_d++) = *(pz_s++)) {
|
||||
case NUL:
|
||||
goto loopDone;
|
||||
|
||||
case '\'':
|
||||
if (pz_d - pz_d_start >= smax - sizeof( zQ )-1)
|
||||
return (char*)NULL;
|
||||
strcpy( pz_d-1, zQ );
|
||||
pz_d += sizeof( zQ )-2;
|
||||
}
|
||||
} loopDone:;
|
||||
pz_d[-1] = '\'';
|
||||
*pz_d = NUL;
|
||||
|
||||
return pz_d;
|
||||
}
|
||||
|
||||
#endif
|
||||
232
gcc/gcc/fixinc/fixlib.h
Normal file
232
gcc/gcc/fixinc/fixlib.h
Normal file
@@ -0,0 +1,232 @@
|
||||
|
||||
/* Install modified versions of certain ANSI-incompatible system header
|
||||
files which are fixed to work correctly with ANSI C and placed in a
|
||||
directory that GCC will search.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef GCC_FIXLIB_H
|
||||
#define GCC_FIXLIB_H
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "tm.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __BEOS__
|
||||
#include "gnu-regex.h"
|
||||
#define xregcomp regcomp
|
||||
#define xregexec regexec
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
#define TOUPPER(c) toupper((c))
|
||||
#define ISIDNUM(c) (isalnum((c))||(c)=='_')
|
||||
#endif
|
||||
|
||||
#include "machname.h"
|
||||
#include "libiberty.h"
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
# define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
typedef int t_success;
|
||||
|
||||
#define FAILURE (-1)
|
||||
#define SUCCESS 0
|
||||
#define PROBLEM 1
|
||||
|
||||
#define SUCCEEDED(p) ((p) == SUCCESS)
|
||||
#define SUCCESSFUL(p) SUCCEEDED (p)
|
||||
#define FAILED(p) ((p) < SUCCESS)
|
||||
#define HADGLITCH(p) ((p) > SUCCESS)
|
||||
|
||||
#ifndef DEBUG
|
||||
# define STATIC static
|
||||
#else
|
||||
# define STATIC
|
||||
#endif
|
||||
|
||||
#define tSCC static const char
|
||||
#define tCC const char
|
||||
#define tSC static char
|
||||
|
||||
/* If this particular system's header files define the macro `MAXPATHLEN',
|
||||
we happily take advantage of it; otherwise we use a value which ought
|
||||
to be large enough. */
|
||||
#ifndef MAXPATHLEN
|
||||
# define MAXPATHLEN 4096
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
#define EXIT_BROKEN 3
|
||||
|
||||
#define NUL '\0'
|
||||
|
||||
#ifndef NOPROCESS
|
||||
#define NOPROCESS ((pid_t) -1)
|
||||
#define NULLPROCESS ((pid_t)0)
|
||||
|
||||
#define EXIT_PANIC 99
|
||||
#endif /* NOPROCESS */
|
||||
|
||||
#define IGNORE_ARG(a) ((void)(a))
|
||||
|
||||
typedef enum t_bool
|
||||
{
|
||||
BOOL_FALSE, BOOL_TRUE
|
||||
} t_bool;
|
||||
|
||||
typedef int apply_fix_p_t; /* Apply Fix Predicate Type */
|
||||
|
||||
#define APPLY_FIX 0
|
||||
#define SKIP_FIX 1
|
||||
|
||||
#define ENV_TABLE \
|
||||
_ENV_( pz_machine, BOOL_TRUE, "TARGET_MACHINE", \
|
||||
"output from config.guess" ) \
|
||||
\
|
||||
_ENV_( pz_orig_dir, BOOL_TRUE, "ORIGDIR", \
|
||||
"directory of fixincl and applyfix" ) \
|
||||
\
|
||||
_ENV_( pz_src_dir, BOOL_TRUE, "SRCDIR", \
|
||||
"directory of original files" ) \
|
||||
\
|
||||
_ENV_( pz_input_dir, BOOL_TRUE, "INPUT", \
|
||||
"current directory for fixincl" ) \
|
||||
\
|
||||
_ENV_( pz_dest_dir, BOOL_TRUE, "DESTDIR", \
|
||||
"output directory" ) \
|
||||
\
|
||||
_ENV_( pz_verbose, BOOL_FALSE, "VERBOSE", \
|
||||
"amount of user entertainment" ) \
|
||||
\
|
||||
_ENV_( pz_find_base, BOOL_TRUE, "FIND_BASE", \
|
||||
"leader to trim from file names" )
|
||||
|
||||
/* Test Descriptor
|
||||
|
||||
Each fix may have associated tests that determine
|
||||
whether the fix needs to be applied or not.
|
||||
Each test has a type (from the te_test_type enumeration);
|
||||
associated test text; and, if the test is TT_EGREP or
|
||||
the negated form TT_NEGREP, a pointer to the compiled
|
||||
version of the text string.
|
||||
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
TT_TEST, TT_EGREP, TT_NEGREP, TT_FUNCTION
|
||||
} te_test_type;
|
||||
|
||||
typedef struct test_desc tTestDesc;
|
||||
|
||||
struct test_desc
|
||||
{
|
||||
te_test_type type;
|
||||
const char *pz_test_text;
|
||||
regex_t *p_test_regex;
|
||||
};
|
||||
|
||||
typedef struct patch_desc tPatchDesc;
|
||||
|
||||
/* Fix Descriptor
|
||||
|
||||
Everything you ever wanted to know about how to apply
|
||||
a particular fix (which files, how to qualify them,
|
||||
how to actually make the fix, etc...)
|
||||
|
||||
NB: the FD_ defines are BIT FLAGS, even though
|
||||
some are mutually exclusive
|
||||
|
||||
*/
|
||||
#define FD_MACH_ONLY 0x0000
|
||||
#define FD_MACH_IFNOT 0x0001
|
||||
#define FD_SHELL_SCRIPT 0x0002
|
||||
#define FD_SUBROUTINE 0x0004
|
||||
#define FD_REPLACEMENT 0x0008
|
||||
#define FD_SKIP_TEST 0x8000
|
||||
|
||||
typedef struct fix_desc tFixDesc;
|
||||
struct fix_desc
|
||||
{
|
||||
tCC* fix_name; /* Name of the fix */
|
||||
tCC* file_list; /* List of files it applies to */
|
||||
tCC** papz_machs; /* List of machine/os-es it applies to */
|
||||
int test_ct;
|
||||
int fd_flags;
|
||||
tTestDesc* p_test_desc;
|
||||
tCC** patch_args;
|
||||
long unused;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int type_name_len;
|
||||
tCC* pz_type;
|
||||
tCC* pz_TYPE;
|
||||
tCC* pz_gtype;
|
||||
} t_gnu_type_map;
|
||||
|
||||
extern int gnu_type_map_ct;
|
||||
|
||||
#ifdef HAVE_MMAP_FILE
|
||||
#define UNLOAD_DATA() do { if (curr_data_mapped) { \
|
||||
munmap ((void*)pz_curr_data, data_map_size); close (data_map_fd); } \
|
||||
else free ((void*)pz_curr_data); } while(0)
|
||||
#else
|
||||
#define UNLOAD_DATA() free ((void*)pz_curr_data)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported procedures
|
||||
*/
|
||||
char * load_file_data ( FILE* fp );
|
||||
|
||||
#ifdef IS_CXX_HEADER_NEEDED
|
||||
t_bool is_cxx_header ( tCC* filename, tCC* filetext );
|
||||
#endif /* IS_CXX_HEADER_NEEDED */
|
||||
|
||||
#ifdef SKIP_QUOTE_NEEDED
|
||||
tCC* skip_quote ( char q, char* text );
|
||||
#endif
|
||||
|
||||
void compile_re ( tCC* pat, regex_t* re, int match, tCC *e1, tCC *e2 );
|
||||
|
||||
void apply_fix ( tFixDesc* p_fixd, tCC* filname );
|
||||
apply_fix_p_t
|
||||
run_test ( tCC* t_name, tCC* f_name, tCC* text );
|
||||
|
||||
#ifdef SEPARATE_FIX_PROC
|
||||
char* make_raw_shell_str ( char* pz_d, tCC* pz_s, size_t smax );
|
||||
#endif
|
||||
|
||||
#ifdef MN_NAME_PAT
|
||||
void mn_get_regexps ( regex_t** label_re, regex_t** name_re, tCC *who );
|
||||
#endif
|
||||
#endif /* ! GCC_FIXLIB_H */
|
||||
158
gcc/gcc/fixinc/fixtests.c
Normal file
158
gcc/gcc/fixinc/fixtests.c
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
/*
|
||||
|
||||
Test to see if a particular fix should be applied to a header file.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
= = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
NOTE TO DEVELOPERS
|
||||
|
||||
The routines you write here must work closely with fixincl.c.
|
||||
|
||||
Here are the rules:
|
||||
|
||||
1. Every test procedure name must be suffixed with "_test".
|
||||
These routines will be referenced from inclhack.def, sans the suffix.
|
||||
|
||||
2. Use the "TEST_FOR_FIX_PROC_HEAD()" macro _with_ the "_test" suffix
|
||||
(I cannot use the ## magic from ANSI C) for defining your entry point.
|
||||
|
||||
3. Put your test name into the FIX_TEST_TABLE
|
||||
|
||||
4. Do not write anything to stdout. It may be closed.
|
||||
|
||||
5. Write to stderr only in the event of a reportable error
|
||||
In such an event, call "exit(1)".
|
||||
|
||||
= = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "fixlib.h"
|
||||
|
||||
#define _ENV_(v,m,n,t) extern tCC* v;
|
||||
ENV_TABLE
|
||||
#undef _ENV_
|
||||
|
||||
typedef apply_fix_p_t t_test_proc ( tCC* file, tCC* text );
|
||||
|
||||
typedef struct {
|
||||
tCC* test_name;
|
||||
t_test_proc* test_proc;
|
||||
} test_entry_t;
|
||||
|
||||
#define FIX_TEST_TABLE \
|
||||
_FT_( "machine_name", machine_name_test ) \
|
||||
_FT_( "stdc_0_in_system_headers", stdc_0_in_system_headers_test )
|
||||
|
||||
#define TEST_FOR_FIX_PROC_HEAD( test ) \
|
||||
static apply_fix_p_t test ( tCC* fname ATTRIBUTE_UNUSED, \
|
||||
tCC* text ATTRIBUTE_UNUSED )
|
||||
|
||||
TEST_FOR_FIX_PROC_HEAD( machine_name_test )
|
||||
{
|
||||
#ifndef MN_NAME_PAT
|
||||
return SKIP_FIX;
|
||||
#else
|
||||
regex_t *label_re, *name_re;
|
||||
regmatch_t match[2];
|
||||
tCC *base, *limit;
|
||||
IGNORE_ARG(fname);
|
||||
|
||||
mn_get_regexps(&label_re, &name_re, "machine_name_test");
|
||||
|
||||
for (base = text;
|
||||
xregexec (label_re, base, 2, match, 0) == 0;
|
||||
base = limit)
|
||||
{
|
||||
base += match[0].rm_eo;
|
||||
/* We're looking at an #if or #ifdef. Scan forward for the
|
||||
next non-escaped newline. */
|
||||
limit = base;
|
||||
do
|
||||
{
|
||||
limit++;
|
||||
limit = strchr (limit, '\n');
|
||||
if (!limit)
|
||||
return SKIP_FIX;
|
||||
}
|
||||
while (limit[-1] == '\\');
|
||||
|
||||
/* If the 'name_pat' matches in between base and limit, we have
|
||||
a bogon. It is not worth the hassle of excluding comments,
|
||||
because comments on #if/#ifdef/#ifndef lines are rare,
|
||||
and strings on such lines are illegal.
|
||||
|
||||
REG_NOTBOL means 'base' is not at the beginning of a line, which
|
||||
shouldn't matter since the name_re has no ^ anchor, but let's
|
||||
be accurate anyway. */
|
||||
|
||||
if (xregexec (name_re, base, 1, match, REG_NOTBOL))
|
||||
return SKIP_FIX; /* No match in file - no fix needed */
|
||||
|
||||
/* Match; is it on the line? */
|
||||
if (match[0].rm_eo <= limit - base)
|
||||
return APPLY_FIX; /* Yup */
|
||||
|
||||
/* Otherwise, keep looking... */
|
||||
}
|
||||
return SKIP_FIX;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TEST_FOR_FIX_PROC_HEAD( stdc_0_in_system_headers_test )
|
||||
{
|
||||
#ifdef STDC_0_IN_SYSTEM_HEADERS
|
||||
return (pz_machine == NULL) ? APPLY_FIX : SKIP_FIX;
|
||||
#else
|
||||
return APPLY_FIX;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
test for fix selector
|
||||
|
||||
THIS IS THE ONLY EXPORTED ROUTINE
|
||||
|
||||
*/
|
||||
apply_fix_p_t
|
||||
run_test( tCC* tname, tCC* fname, tCC* text )
|
||||
{
|
||||
#define _FT_(n,p) { n, p },
|
||||
static test_entry_t test_table[] = { FIX_TEST_TABLE { NULL, NULL }};
|
||||
#undef _FT_
|
||||
#define TEST_TABLE_CT (ARRAY_SIZE (test_table)-1)
|
||||
|
||||
int ct = TEST_TABLE_CT;
|
||||
test_entry_t* pte = test_table;
|
||||
|
||||
do
|
||||
{
|
||||
if (strcmp( pte->test_name, tname ) == 0)
|
||||
return (*pte->test_proc)( fname, text );
|
||||
pte++;
|
||||
} while (--ct > 0);
|
||||
fprintf( stderr, "fixincludes error: the `%s' fix test is unknown\n",
|
||||
tname );
|
||||
exit( 3 );
|
||||
}
|
||||
Reference in New Issue
Block a user