This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Tools to generate the ARI bug lists


Just FYI, the breakdown of what came from where is in:
  http://sources.redhat.com/gdb/current/ari/ari.source.bug
(I only very recently added a link to this).  The script is attached.

Andrew
#!/bin/sh -x

# TODO: setjmp.h, setjmp and longjmp.


PATH=/bin:/usr/bin:/usr/local/bin:$HOME/bin
export PATH

# Direct stderr into stdout but still hang onto stderr (/dev/fd/3)
exec 3>&2 2>&1
ECHO ()
{
#   echo "$@" | tee /dev/fd/3 1>&2
    echo "$@" 1>&2
    echo "$@" 1>&3
}

# Really mindless usage
if test $# -ne 4
then
    echo "Usage: $0 <snapshot> <tmpdir> <destdir> <project>" 1>&2
    exit 1
fi
snapshot=$1 ; shift
tmpdir=$1 ; shift
wwwdir=$1 ; shift
project=$1 ; shift

if [ ! -w ${wwwdir} -o ! -d ${wwwdir} ]
then
  echo ERROR: Can not write to directory ${wwwdir} >&2
  exit 2
fi

if [ ! -r ${snapshot} ]
then
    echo ERROR: Can not read snapshot file 1>&2
    exit 1
fi

# FILE formats
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
# Where ``*'' is {source,warning,format,doschk}

ARI_REGRESSION=0
ARI_DEPRECATED=1
ARI_CODE=2
ARI_WARNING=3
ARI_INFO=4

ARI_FIRST=$ARI_CODE

unpack_source_p=true
delete_source_p=true

check_warning_p=false # broken
check_format_p=false # broken
check_source_p=true
check_doschk_p=true
check_werror_p=true

update_web_p=true


if awk --version 2>&1 </dev/null | grep -i gnu > /dev/null
then
  AWK=awk
else
  AWK=gawk
fi


# Set up a few cleanups
if ${delete_source_p}
then
    trap "cd /tmp; rm -rf ${tmpdir}; exit" 0 1 2 15
fi


# unpack the tar-ball
if ${unpack_source_p}
then
    /bin/rm -rf ${tmpdir}
    /bin/mkdir ${tmpdir}
    if [ ! -d ${tmpdir} ]
    then
	echo "Problem creating work directory"
	exit 1
    fi
    cd ${tmpdir} || exit 1
    echo `date`: Unpacking tar-ball ...
    case ${snapshot} in
	*.tar.bz2 ) bzcat ${snapshot} ;;
	*.tar ) cat ${snapshot} ;;
	* ) ECHO Bad file ${snapshot} ; exit 1 ;;
    esac | tar xf -
fi
module=`basename ${snapshot}`
module=`basename ${module} .bz2`
module=`basename ${module} .tar`
srcdir=`echo ${tmpdir}/${module}*`
version_in=${srcdir}/gdb/version.in
if [ ! -r ${version_in} ]
then
    echo ERROR: missing version file 1>&2
    exit 1
fi
version=`cat ${version_in}`


# THIS HAS SUFFERED BIT ROT
if ${check_warning_p} && test -d "${srcdir}"
then
    echo `date`: Parsing compiler warnings 1>&2
    $AWK < ${root}/ari.compile '
BEGIN {
    FS=":";
}
/^[^:]*:[0-9]*: warning:/ {
  file = $1;
  #sub (/^.*\//, "", file);
  warning[file] += 1;
}
/^[^:]*:[0-9]*: error:/ {
  file = $1;
  #sub (/^.*\//, "", file);
  error[file] += 1;
}
END {
  for (file in warning) {
    print file ":warning:" level[file]
  }
  for (file in error) {
    print file ":error:" level[file]
  }
}
' > ${root}/ari.warning.bug
fi



# THIS HAS SUFFERED BIT ROT
if ${check_format_p} && test -d "${srcdir}"
then
    printf "Analizing file formatting:" 1>&2
    ( cd "${srcdir}/${project}" && ls | sed -n -e '/\.[hc]$/p'
    ) | while read f
    do
	printf " $f" 1>&2
	lines=`( indent < "${srcdir}/${project}/${f}" | diff -e - "${srcdir}/${project}/${f}" ) 2>&1 | wc -l`
	if test $lines -gt 0
	then
	    echo ${f}:format:`echo ${lines}`
	fi
    done > ${wwwdir}/ari.format.bug
    echo ""
fi



if ${check_source_p} && test -d "${srcdir}"
then
    echo "`date`: Checking source code" 1>&2
    rm -f ${wwwdir}/ari.source.*
    find "${srcdir}/${project}" \
	-name 'testsuite' -prune \
	-o -name 'stop-gdb.c' -prune \
	-o -name 'stuff.c' -prune \
	-o -name '*-stub.c' -prune \
	-o -name '*-share' -prune \
	-o -name 'tui' -prune \
	-o -name 'nlm' -prune \
	-o -name 'gnu-regex.c' -prune \
	-o -name 'gnu-regex.h' -prune \
	-o -name '*\.tab\.c' -prune \
	-o -name 'gdbserver' -prune \
	-o -name '*.[hc]' -type f -print \
	| $AWK > ${wwwdir}/ari.source.bug '
BEGIN {
    comment_p = 0
    string_p = 0
}

function fail (bug) {
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    if (fixit[bug, file] > 0) {
	fixit[bug, file] -= 1
    } else {
	print bug ":" 1 ":" level[bug] ":" file ":" FNR
	total[bug] += 1
    }
}

function fix(bug, file, count) {
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    # print bug ":" -count ":" level[bug] ":" file ":" 0
    fixit[bug, file] = count
}

# Load the list of files into an initially empty argument list.
# While STDIN is being parsed, ARGIND will remain zero.
ARGIND == 0 {
    ARGV[ARGC++] = $0;
    next;
}

# Initialize the PARSER
FNR == 1 {
    file = FILENAME;
    sub (/^.*\/'"${project}"'\//, "", file);
    file = "'"${project}"'/" file
    #printf " %s", file > "/dev/stderr";
    #fflush (/dev/stderr);
}

# Skip deprecated/obsolete lines
/(^|[^_[:alnum:]])OBSOLETE([^_[:alnum:]]|$)/ { next; }

# Things in comments

BEGIN { doc["GNU/Linux"] = "\
Use either ``GNU/Linux'\'\'' or ``Linux kernel'\'\'' in comments.  \
This test assumes that the word ``Linux'\'\'' appears on the same line \
as the ``GNU'\'\'' or ``kernel'\'\''."
    level["GNU/Linux"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])Linux([^_[:alnum:]]|$)/ \
&& !/(^|[^_[:alnum:]])GNU\/Linux([^_[:alnum:]]|$)/ \
&& !/(^|[^_[:alnum:]])Linux kernel([^_[:alnum:]]|$)/ {
    fail("GNU/Linux")
}


# SNIP - Strip out comments - SNIP


FNR == 1 { comment_p = 0; }
comment_p && /\*\// { gsub (/^([^\*]|\*+[^\/\*])*\*+\//, " "); comment_p = 0; }
comment_p { next; }
!comment_p { gsub (/\/\*([^\*]|\*+[^\/\*])*\*+\//, " "); }
!comment_p && /\/\*/ { gsub (/\/\*.*$/, " "); comment_p = 1; }

BEGIN { doc["error capital"] = "\
An error message should start with a capital letter"
    level["error capital"] = '$ARI_INFO'
}
/(^[^_[:alnum:]])error([^_[:alnum:]]|$)\([[:space:]]*"[^A-Z]*[^\/]"/ {
    fail("error capital")
}

BEGIN { doc["error full-stop"] = "\
An error message should not have a trailing full-stop"
    level["error full-stop"] = '$ARI_REGRESSION'
}
/(^[^_[:alnum:]])error([^_[:alnum:]]|$)\([[:space:]]*"[^"]\."/ {
    fail("error full-stop")
}

# Include files for which GDB has a custom version.

BEGIN { doc["assert.h"] = "\
Instead of assert.h, use gdb_assert.h";
    level["assert.h"] = '$ARI_REGRESSION'
    fix("assert.h", "gdb/gdb_assert.h", 0) # it does not use it
}
/^#[[:blank:]]*include[[:blank:]]+.assert\.h./ {
    fail("assert.h")
}

BEGIN { doc["dirent.h"] = "\
Instead of dirent.h, use gdb_dirent.h";
    level["dirent.h"] = '$ARI_REGRESSION'
    fix("dirent.h", "gdb/gdb_dirent.h", 1);
}
/^#[[:blank:]]*include[[:blank:]]*.dirent\.h./ {
    fail("dirent.h")
}

BEGIN { doc["proc_service.h"] = "\
Instead of proc_service.h, use gdb_proc_service.h";
    level["proc_service.h"] = '$ARI_CODE'
    fix("proc_service.h", "gdb/gdb_proc_service.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.proc_service\.h./ {
    fail("proc_service.h")
}

BEGIN { doc["regex.h"] = "\
Instead of regex.h, use gdb_regex.h";
    level["regex.h"] = '$ARI_REGRESSION'
    fix("regex.h", "gdb/gdb_regex.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.regex\.h./ {
    fail("regex.h")
}

BEGIN { doc["xregex.h"] = "\
Instead of xregex.h, use gdb_regex.h";
    level["xregex.h"] = '$ARI_REGRESSION'
    fix("xregex.h", "gdb/gdb_regex.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.xregex\.h./ {
    fail("xregex.h")
}

BEGIN { doc["gnu-regex.h"] = "\
Instead of gnu-regex.h, use gdb_regex.h";
    level["gnu-regex.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.gnu-regex\.h./ {
    fail("gnu regex.h")
}

BEGIN { doc["stat.h"] = "\
Instead of stat.h or sys/stat.h, use gdb_stat.h";
    level["stat.h"] = '$ARI_CODE'
    fix("stat.h", "gdb/gdb_stat.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.stat\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.sys\/stat\.h./ {
    fail("stat.h")
}

BEGIN { doc["string.h"] = "\
Instead of string.h, strings.h or memory.h, use gdb_string.h";
    level["string.h"] = '$ARI_REGRESSION'
    fix("string.h", "gdb/gdb_string.h", 4)
}
/^#[[:blank:]]*include[[:blank:]]*.string\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.strings\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.memory\.h./ {
    fail("string.h")
}

BEGIN { doc["thread_db.h"] = "\
Instead of thread_db.h, use gdb_thread_db.h";
    fix("thread_db.h", "gdb/gdb_thread_db.h", 1);
    level["thread_db.h"] = '$ARI_CODE'
}
/^#[[:blank:]]*include[[:blank:]]*.thread_db\.h./ {
    fail("thread_db.h")
}

BEGIN { doc["wait.h"] = "\
Instead of wait.h or sys/wait.h, use gdb_wait.h";
    fix("wait.h", "gdb/gdb_wait.h", 2);
    level["wait.h"] = '$ARI_CODE'
}
/^#[[:blank:]]*include[[:blank:]]*.wait\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.sys\/wait\.h./ {
    fail("wait.h")
}

BEGIN { doc["vfork.h"] = "\
Instead of vfork.h, use gdb_vfork.h";
    fix("vfork.h", "gdb/gdb_vfork.h", 1);
    level["vfork.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.vfork\.h./ {
    fail("vfork.h")
}

BEGIN { doc["Xm-OS.h"] = "\
Some config/ARCH/Xm-OS.h files use #include \"Xm-OS.h\".  To include the \
file \"config/Xm-OS.h\".  They should use the latter path."
    level["Xm-OS.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.nm-[^\.]*\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.tm[^\.]*-\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.xm-[^\.]*\.h./ {
    fail("Xm-OS.h")
}

BEGIN { doc["error printing internal error"] = "\
Code should call the internal_error() function rather than print an \
internal-error message directly";
    level["error printing internal error"] = '$ARI_WARNING'
}
/error.*\"Internal error/ || /error.*\"internal error/ {
    fail("error printing internal error")
}

BEGIN { doc["%p"] = "\
Use %s and paddr() to print target addresses, not %p.";
    level["%p"] = '$ARI_CODE'
}
/%p/ && !/%prec/ {
    fail("%p")
}

BEGIN { doc["%ll"] = "\
Use %s and phex() et.al. to print long long values, not %ll.";
    level["%ll"] = '$ARI_CODE'
}
/%ll/ {
    fail("%ll")
}


# SNIP - Strip out strings - SNIP


# awk
# Test on top.c, scm-valprint.c, remote-rdi.c, ada-lang.c
FNR == 1 { string_p = 0; }
# Strip escaped characters.
{ gsub(/\\./, "."); }
# Strip quoted quotes.
{ gsub(/'\''.'\''/, "'\''.'\''"); }
# End of multi-line string
string_p && /\"/ {
    # print "EOS:", $0;
    gsub (/^[^\"]*\"/, "'\''");
    string_p = 0;
}
# Middle of multi-line string, discard line.
string_p {
    # print "MOS:", $0;
    $0 = ""
}
# Strip complete strings from the middle of the line
!string_p {
    # print "COS:", $0;
    gsub (/\"[^\"]*\"/, "'\'\''");
}
# Start of multi-line string
!string_p && /\"/ {
    # print "SOS:", $0;
    gsub (/\"[^\"]*$/, "'\''");
    string_p = 1;
}
# { print }


# Accumulate continuation lines
FNR == 1 { cont_p = 0; }
!cont_p { full_line = ""; }
/[^\\]\\$/ { gsub (/\\$/, ""); full_line = full_line $0; cont_p = 1; next; }
cont_p { $0 = full_line $0; cont_p = 0; full_line = ""; }


# GDB uses ISO C.  Check for any non pure ISO C code

BEGIN { doc["PARAMS"] = "\
Still uses the PARAMS macro.";
    level["PARAMS"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])PARAMS([^_[:alnum:]]|$)/ {
    fail("PARAMS")
}

BEGIN { doc["__STDC__"] = "\
GDB assumes ISO C, testing for __STDC__ makes little sense";
    level["__STDC__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__STDC__([^_[:alnum:]]|$)/ {
    fail("__STDC__")
}

BEGIN { doc["__func__"] = "\
__func__ is a post ISO C 90 extension.  EGCS 1.1.2, for instance, does not \
support it."
    level["__func__"] = '$ARI_REGRESSION'
    fix("__func__", "gdb/gdb_assert.h", 1)
}
/(^|[^_[:alnum:]])__func__([^_[:alnum:]]|$)/ {
    fail("__func__")
}

BEGIN { doc["__FUNCTION__"] = "\
__FUNCTION__ is a post ISO C 90 extension."
    level["__FUNCTION__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__FUNCTION__([^_[:alnum:]]|$)/ {
    fail("__FUNCTION__")
}

BEGIN { doc["__CYGWIN32__"] = "\
__CYGWIN32__ has been replaced by __CYGWIN__ or, better, explicit \
autoconf tests";
    level["__CYGWIN32__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__CYGWIN32__([^_[:alnum:]]|$)/ {
    fail("__CYGWIN32__")
}

BEGIN { doc["PTR"] = "\
Use ``void *'\'\''.  PTR dates back to the days before ISO C.";
    level["PTR"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])PTR([^_[:alnum:]]|$)/ {
    fail("PTR")
}

BEGIN { doc["//"] = "\
C++ comments - // - are not valid ISO C."
    level["//"] = '$ARI_REGRESSION'
}
/\/\// {
    fail("//")
}

BEGIN { doc["CONST_PTR"] = "\
Use ``const void *'\'\''.  PTR dates back to the days before ISO C.";
    level["CONST_PTR"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])CONST_PTR([^_[:alnum:]]|$)/ {
    fail("CONST_PTR")
}

BEGIN { doc["grep ^func"] = "\
A function declaration with the function name positioned at the very start \
of a line.  Only as part of the function definition should the function \
name appear at the very start of a line.  This is so that \
``grep ^func'\'\'' works";
    level["grep ^func"] = '$ARI_CODE'
}
{ grep_func = 0; }
/^[[:alnum:]_]+[[:blank:]]*\([[:blank:]]*[^\*].*\);[[:blank:]]*/ {
    # FYI, it matches:
    #NAME (...);
    # when a normal declaration would have:
    #TYPE NAME (...);
    fail("grep ^func")
    grep_func = 1;
}

BEGIN { doc["K&R defn"] = "\
Still uses an old style K&R function definition (not declaration). \
This check also trips up on incorrectly indented function declarations \
(see ``grep ^func'\'\'')."
    level["K&R defn"] = '$ARI_REGRESSION'
    fix("K&R defn", "gdb/ser-go32.c", 2)
}
/^[[:alnum:]_]+[[:blank:]]*\([[:alnum:]_]*[[:blank:]]*[,\)]/ && \
! /\(void\)/ && ! /\);/ && !grep_func {
    fail("K&R defn")
}

BEGIN { doc["hash"] = "\
Some compilers will only corectly parse a preprocessor directive when the \
``#'\'\'' is the first character on the line. \
"
    level["hash"] = '$ARI_REGRESSION'
}
/^[[:blank:]]+#/ {
    fail("hash")
}

BEGIN { doc["#define JB_..."] = "\
The system header <setjmp.h> is free to define macros with the JB_ prefix.\
    level["#define JB_..."] = '$ARI_CODE'
}
/^#[[:space:]]*define[[:space:]]*JB_/ {
    fail("#define JB_...")
}

BEGIN { doc["make_cleanup_func"] = "\
Type casting using make_cleanup_func is invalid ISO C";
    level["make_cleanup_func"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])make_cleanup_func([^_[:alnum:]]|$)/ {
    fail("make_cleanup_func")
}

BEGIN { doc["catch_errors_ftype"] = "\
Type casting using catch_errors_ftype is invalid ISO C";
    level["catch_errors_ftype"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])catch_errors_ftype([^_[:alnum:]]|$)/ {
    fail("catch_errors_ftype")
}

BEGIN { doc["catch_errors"] = "\
Use catch_exceptions() in preference to catch_errors().";
    level["catch_errors"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])catch_errors[[:space:]]*\(/ {
    fail("catch_errors")
}

BEGIN { doc["strerror"] = "\
Use safe_strerror() in preference to strerror().";
    level["strerror"] = '$ARI_REGRESSION'
    fix("strerror", "gdb/gdb_string.h", 2)
    fix("strerror", "gdb/utils.c", 1)
}
/(^|[^_[:alnum:]])strerror[[:space:]]*\(/ {
    fail("strerror")
}

BEGIN { doc["long long"] = "\
Change ``long long'\'\'' to ``LONGEST'\'\''.";
    level["long long"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])long[[:space:]]+long([^_[:alnum:]]|$)/ {
    fail("long long")
}

BEGIN { doc["ATTRIBUTE_UNUSED"] = "\
GDB is compiled with -Werror and, consequently, is not able to tolerate \
false warnings.  Since -Wunused-param produces such warnings, neither \
that warning flag nor ATTRIBUTE_UNUSED are used in GDB."
    level["ATTRIBUTE_UNUSED"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])ATTRIBUTE_UNUSED([^_[:alnum:]]|$)/ {
    fail("ATTRIBUTE_UNUSED")
}

# General problems

BEGIN { doc["_func"] = "\
The suffixes ..._func and ..._ftype are used inconsistently in the source. \
Perhaps just ..._ftype should be used.";
    level["_func"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])[[:alpha:]_][[:alnum:]_]*_func([^_[:alnum:]]|$)/ {
    fail("_func")
}

BEGIN { doc["TARGET_BYTE_ORDER_SELECTABLE"] = "\
This macro is made redundant by multi-arch."
    level["TARGET_BYTE_ORDER_SELECTABLE"] = '$ARI_REGRESSION'
}
/TARGET_BYTE_ORDER_SELECTABLE/ {
    fail("TARGET_BYTE_ORDER_SELECTABLE")
}

BEGIN { doc["TARGET_BYTE_ORDER_DEFAULT"] = "\
This macro is made redundant by multi-arch."
    level["TARGET_BYTE_ORDER_DEFAULT"] = '$ARI_REGRESSION'
}
/TARGET_BYTE_ORDER_DEFAULT/ {
    fail("TARGET_BYTE_ORDER_DEFAULT")
}

# Correct use of initialized?
BEGIN {
    doc["_initialize decl"] = "\
Declaration of _initialize*() missing.  The declaration stops a -Wmissing-declarations \
warning from GCC.";
    level["_initialize decl"] = '$ARI_INFO'
    doc["_initialize ftype"] = "\
Declaration of _initialize*() does not use initialize_file_ftype, should it?";
    level["_initialize ftype"] = '$ARI_INFO'
}
# Remember what type declaration, if any, we see
FNR == 1 {
    initialize_decl = 0;
    initialize_ftype = 0;
}
/^extern[[:space:]]+void[[:space:]]+_initialize_[_[:alnum:]]*/ {
    initialize_decl = 1
}
/^extern[[:space:]]+initialize_file_ftype[[:space:]]+_initialize_[_[:alnum:]]*/ {
    initialize_ftype = 1
}
# Check it against the definition
/^_initialize_[_[:alnum:]]*[[:space:]]+/ {
    if (!initialize_decl && !initialize_ftype) {
	fail("_initialize decl")
    }
    if (!initialize_ftype) {
	fail("_initialize ftype")
    }
}

BEGIN { doc["inline"] = "\
Using INLINE generally suggests a micro-optimization - a better \
algorithm will likely produce greater performance improvements. \
Instead let the compiler decide if/when something needs to be \
made inline."
    level["inline"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])inline([^_[:alnum:]]|$)/ {
    fail("inline")
}

BEGIN { doc["register"] = "\
Let the compiler decide if something needs to be made register"
    level["register"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])register([^_[:alnum:]]|$)/ {
    fail("register")
}

BEGIN { doc["return_to_top_level"] = "\
return_to_top_level() is deprecated in favor of the verror(), error_stream() \
et.al.";
    level["return_to_top_level"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])return_to_top_level[[:blank:]]*\(/ {
    fail("return_to_top_level")
}

BEGIN { doc["error_begin"] = "\
error_begin() is deprecated in favor of verror(), error_stream() et.al.";
    level["error_begin"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])error_begin[[:blank:]]*\(/ {
    fail("error_begin")
}

BEGIN { doc["warning_begin"] = "\
warning_begin() is deprecated in favor of vwarning(), warning_stream() \
et.al. (see error_begin())";
    level["warning_begin"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])warning_begin[[:blank:]]*\(/ {
    fail("warning_begin")
}

BEGIN { doc["sizeof CORE_ADDR"] = "\
Taking the sizeof a CORE_ADDR is wrong.  CORE_ADDR is at \
least as big as the target pointer, _not_ the same size.  Use \
TARGET_PTR_BIT or TARGET_ADDR_BIT.";
    level["sizeof CORE_ADDR"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])sizeof[[:blank:]]*\(CORE_ADDR\)/ \
|| /(^|[^_[:alnum:]])sizeof[[:blank:]]*CORE_ADDR([^_[:alnum:]]|$)/ {
    fail("sizeof CORE_ADDR")
}

BEGIN { doc["REGNO"] = "\
Use the ..._REGNUM instead of the ..._REGNO name suffix";
    level["REGNO"] = '$ARI_INFO'
}
/_REGNO([^_[:alnum:]]|$)/ || /_regno([^_[:alnum:]]|$)/ {
    fail("REGNO")
}

BEGIN { doc["abort"] = "\
GDB should never abort - use internal_error()";
    level["abort"] = '$ARI_REGRESSION'
    fix("abort", "gdb/utils.c", 3)
}
/(^|[^_[:alnum:]])abort[[:blank:]]*\(/ {
    fail("abort")
}

BEGIN { doc["basename"] = "\
GDB should never basename - use ``const char *lbasename(const char *)'\'\''";
    level["basename"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])basename[[:blank:]]*\(/ {
    fail("basename")
}

BEGIN { doc["assert"] = "\
GDB should never use assert().  Assert() calls abort() and GDB should \
not abort.  Use internal_error() or gdb_assert() instead.";
    level["assert"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])assert[[:blank:]]*\(/ {
    fail("assert")
}

BEGIN { doc["CORE_ADDR cast"] = "\
Casting something to a CORE_ADDR is typically dangerous and non-portable. \
(The data from this pattern may be wrong)";
    level["CORE_ADDR cast"] = '$ARI_WARNING'
}
/\(CORE_ADDR\)[:blank:]*[^,);]/ {
    fail("CORE_ADDR cast")
}

BEGIN { doc["QUIT"] = "\
Uses QUIT which could be unsafe. Should it instead use ``if (QUIT_P ()) \
return ...;'\'\'' (which does not yet exist)."
    level["QUIT"] = '$ARI_INFO'
}
/QUIT[[:blank:]]*[^;]/ {
    fail("QUIT")
}

BEGIN { doc["quit_flag"] = "\
Uses ``quit_flag'\'\''.  Should it instead use ``if (QUIT_P ()) ...'\'\'' \
(which does not yet exist).";
    level["quit_flag"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])quit_flag([^_[:alnum:]]|$)/ {
    fail("quit_flag")
}

BEGIN { doc["extern"] = "\
An ``extern'\'\'' declaration appears in a .c file";
    level["extern"] = '$ARI_WARNING'
    fix("extern", "gdb/ser-go32.c", 1) # extern *environ;
}
/^[[:blank:]]*extern[[:blank:]]*/ && ! /_initialize_/ && file ~ /\.c$/ { 
    fail("extern")
}

BEGIN { doc["#define"] = "\
Delcare an enum in preference to define a macro. ???";
    level["#define"] = '$ARI_INFO'
}
/^#[[:blank:]]*define[[:blank:]]+[[:alnum:]_]+[[:blank:]]+/ {
    fail("#define")
}

BEGIN { doc["#if"] = "\
Use an if statement in preference to conditionally compiled code. ???";
    level["#if"] = '$ARI_INFO'
}
/^#[[:blank:]]*if/ && ! / HAVE_/ {
    fail("#if")
}

BEGIN { doc["GDBTK"] = "\
#ifdef GDBTK should not be needed.";
    level["GDBTK"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])GDBTK([^_[:alnum:]]|$)/ {
    fail("GDBTK")
}

BEGIN { doc["TUI"] = "\
#ifdef TUI should not be needed.";
    level["TUI"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])TUI([^_[:alnum:]]|$)/ {
    fail("TUI")
}

BEGIN { doc["HAVE_VFORK"] = "\
#ifdef HAVE_VFORK is redundant.  Include \"gdb_vfork.h\" and call vfork() \
unconditionally.";
    level["HAVE_VFORK"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])HAVE_VFORK([^_[:alnum:]]|$)/ {
    fail("HAVE_VFORK")
}

BEGIN { doc["DEBUG"] = "\
Nothing should depend on a macro like DEBUG"
    level["DEBUG"] = '$ARI_INFO'
}
/^#[[:blank:]]*if.*DEBUG/ {
    fail("DEBUG")
}

BEGIN { doc["union"] = "\
The union construct always leads to problems...";
    level["union"] = '$ARI_INFO'
}
/[[:blank:]]*union[[:blank:]]*/ {
    fail("union")
}

BEGIN { doc["unsafe getpkt"] = "\
Function that can call longjmp.";
    level["unsafe getpkt"] = '$ARI_INFO'
}
/^[^_[:alnum:]]getpkt([^_[:alnum:]]|$)/ {
    fail("unsafe getpkt")
}

BEGIN { doc["unsafe error"] = "\
Function that can can call longjmp.";
    level["unsafe error"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])error[[:blank:]]*\(/ {
    fail("unsafe error")
}

BEGIN { doc["readchar"] = "\
Parameterise the remote serial read/write code with the serial device \
being read.";
    level["readchar"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])readchar[[:blank:]]*\(/ {
    fail("readchar")
}

BEGIN { doc["sigsetmask"] = "\
sigsetmask() should be replaced by sigprocmask().";
    level["sigsetmask"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])sigsetmask[[:blank:]]*\(/ {
    fail("sigsetmask")
}

BEGIN { doc["bcmp"] = "\
bcmp() is deprecated in favor of the ISO C function memcmp().";
    level["bcmp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])bcmp[[:blank:]]*\(/ {
    fail("bcmp")
}

BEGIN { doc["bzero"] = "\
bzero() id deprecated in favour of the ISO C function memset().";
    level["bzero"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])bzero[[:blank:]]*\(/ {
    fail("bzero")
}

BEGIN { doc["bcopy"] = "\
bcopy() id deprecated in favour of the ISO C functions memcpy() and \
memmove().";
    level["bcopy"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])bcopy[[:blank:]]*\(/ {
    fail("bcopy")
}

BEGIN { doc["atoi"] = "\
GDB needs a string to LONGEST conversion function.  Something like \
string_to_core_addr() but in the style of strtol().  The latter has a habit \
of accepting dud strings."
    level["atoi"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])atoi[[:blank:]]*\(/ {
    fail("atoi")
}

BEGIN { doc["strtol"] = "\
GDB needs a string to LONGEST conversion function.  Something like \
string_to_core_addr() but in the style of strtol().  The latter has a habit \
of accepting dud strings."
    level["strtol"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])strtol[[:blank:]]*\(/ {
    fail("strtol")
}

BEGIN { doc["printf"] = "\
All GDB output should use the *printf*filtered() functions.";
    level["printf"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])printf[[:blank:]]*\(/ {
    fail("printf")
}

BEGIN { doc["extract_floating"] = "\
extract_floating() is deprecated in favour of extract_typed_floating().";
    level["extract_floating"] = '$ARI_DEPRECATED'
    fix("extract_floating", "gdb/floatformat.c", 1)
}
/(^|[^_[:alnum:]])extract_floating[[:blank:]]*\(/ {
    fail("extract_floating")
}

BEGIN { doc["store_floating"] = "\
store_floating() is deprecated in favour of store_typed_floating().";
    level["store_floating"] = '$ARI_DEPRECATED'
    fix("store_floating", "gdb/floatformat.c", 1)
}
/(^|[^_[:alnum:]])store_floating[[:blank:]]*\(/ {
    fail("store_floating")
}

BEGIN { doc["floatformat_to_double"] = "\
floatformat_to_double() is deprecated in favour of \
floatformat_to_doublest().";
    level["floatformat_to_double"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])floatformat_to_double[[:blank:]]*\(/ {
    fail("floatformat_to_double")
}

BEGIN { doc["floatformat_from_double"] = "\
floatformat_from_double() is deprecated in favour of \
floatformat_from_doublest().";
    level["floatformat_from_double"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])floatformat_from_double[[:blank:]]*\(/ {
    fail("floatformat_from_double")
}

BEGIN { doc["floatformat_arm_ext"] = "\
GDB should use floatformat_arm_big or floatformat_arm_littlebyte_bigword.";
    level["floatformat_arm_ext"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])floatformat_arm_ext([^_[:alnum:]]|$)/ {
    fail("floatformat_arm_ext")
}

BEGIN { doc["IEEE_FLOAT"] = "\
The macro IEEE_FLOAT is no longer needed.";
    level["IEEE_FLOAT"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])IEEE_FLOAT([^_[:alnum:]]|$)/ {
    fail("IEEE_FLOAT")
}

BEGIN { doc["address of builtin_type"] = "\
The builtin_type* defined in \"gdbtypes.h\" are going to be changed to either \
dynamic variables or functions.  Taking their address - as is often done in \
c-lang.c - will no longer be possible";
    level["address of builtin_type"] = '$ARI_WARNING'
}
/\&builtin_type/ {
    fail("address of builtin_type")
}

BEGIN { doc["FLOAT_INFO"] = "\
The macro FLOAT_INFO is deprecated in favour of PRINT_FLOAT_INFO.";
    level["FLOAT_INFO"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])FLOAT_INFO([^_[:alnum:]]|$)/ {
    fail("FLOAT_INFO")
}

BEGIN { doc["PRINT_REGISTER_HOOK"] = "\
The macro PRINT_REGISTER_HOOK is redundant.  The macro DO_REGISTERS_INFO \
and a helper function can do similar."
    level["PRINT_REGISTER_HOOK"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])PRINT_REGISTER_HOOK([^_[:alnum:]]|$)/ {
    fail("PRINT_REGISTER_HOOK")
}

BEGIN { doc["INVALID_FLOAT"] = "\
The macro INVALID_FLOAT was just just wierd.";
    level["INVALID_FLOAT"] = '$ARI_REGRESSION'
    fix("INVALID_FLOAT", "gdb/vax-tdep.c", 3);
}
/(^|[^_[:alnum:]])INVALID_FLOAT([^_[:alnum:]]|$)/ {
    fail("INVALID_FLOAT")
}

BEGIN { doc["HOST_BYTE_ORDER"] = "\
The macro HOST_BYTE_ORDER is not used.";
    level["HOST_BYTE_ORDER"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])HOST_BYTE_ORDER([^_[:alnum:]]|$)/ {
    fail("HOST_BYTE_ORDER")
}

BEGIN { doc["BIG_ENDIAN"] = "\
The macro BIG_ENDIAN is being replaced with BFD_ENDIAN_BIG.";
    level["BIG_ENDIAN"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])BIG_ENDIAN([^_[:alnum:]]|$)/ {
    fail("BIG_ENDIAN")
}

BEGIN { doc["LITTLE_ENDIAN"] = "\
The macro LITTLE_ENDIAN is being replaced with BFD_ENDIAN_LITTLE.";
    level["LITTLE_ENDIAN"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])LITTLE_ENDIAN([^_[:alnum:]]|$)/ {
    fail("LITTLE_ENDIAN")
}

BEGIN { doc["report_transfer_performance"] = "\
?????";
    level["report_transfer_performance"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])report_transfer_performance([^_[:alnum:]]|$)/ {
    fail("report_transfer_performance")
}

BEGIN { doc["DECR_PC_AFTER_BREAK"] = "\
I wish this would just go away.  An ISA has one or more hardware registers \
that define a processors current execution point in an instruction stream. \
Sometimes those registers specify the instruction about to be executed \
and sometimes one beyond that.  None of this is of interest to core-gdb. \
Instead the architecture should provide a current instruction address \
method that always returns the address of the instruction about to be \
executed (as determined from the hardware registers).";
    level["DECR_PC_AFTER_BREAK"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])DECR_PC_AFTER_BREAK([^_[:alnum:]]|$)/ {
    fail("DECR_PC_AFTER_BREAK")
}

BEGIN { doc["USG"] = "\
What does USG even tell us?";
    level["USG"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])USG([^_[:alnum:]]|$)/ {
    fail("USG")
}

BEGIN { doc["EXTRA_FRAME_INFO"] = "\
The macro EXTRA_FRAME_INFO is replaced by ``struct frame_extra_info'\'\''.";
    level["EXTRA_FRAME_INFO"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])EXTRA_FRAME_INFO([^_[:alnum:]]|$)/ {
    fail("EXTRA_FRAME_INFO")
}

BEGIN { doc["FRAME_FIND_SAVED_REGS"] = "\
The macro FRAME_FIND_SAVED_REGS is replaced by FRAME_INIT_SAVED_REGS.";
    level["FRAME_FIND_SAVED_REGS"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])FRAME_FIND_SAVED_REGS([^_[:alnum:]]|$)/ {
    fail("FRAME_FIND_SAVED_REGS")
}

BEGIN { doc["SIZEOF_FRAME_SAVED_REGS"] = "\
The macro SIZEOF_FRAME_SAVED_REGS typically should not be needed.";
    level["SIZEOF_FRAME_SAVED_REGS"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])SIZEOF_FRAME_SAVED_REGS([^_[:alnum:]]|$)/ {
    fail("SIZEOF_FRAME_SAVED_REGS")
}

BEGIN { doc["strsignal"] = "\
GDB should be using the ABI to convert a signal into a string.";
    level["strsignal"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])strsignal[[:blank:]]*\(/ {
    fail("strsignal")
}

BEGIN { doc["target_signal"] = "\
This is really badly named.  It should be called something like gdb_signal \
as it is GDBs internal representation of the target signal.  It gets worse \
as target_signal_to_host() is actually translating to/from the true target \
signal.";
    level["target_signal"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])target_signal([^_[:alnum:]]|$)/ {
    fail("target_signal")
}

# The register cache and the addition of a frame argument.

BEGIN { doc["registers []"] = "\
Too many cases of code just blatting registers[].  Use existing interfaces \
and mechanisms.";
    level["registers []"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])registers([^_[:alnum:]]|$)/ && ! /->registers([^_[:alnum:]]|$)/ {
    fail("registers []")
}

BEGIN { doc["register_valid []"] = "\
Too many cases of code just blatting register_valid[].  Use existing \
interfaces and mechanisms.";
    level["register_valid []"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])register_valid([^_[:alnum:]]|$)/ {
    fail("register_valid []")
}

BEGIN { doc["read_register_gen in target"] = "\
Target and nat code should fetch values from the cache using \
regcache_collect()."
    level["read_register_gen in target"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])read_register_gen([^_[:alnum:]]|$)/ && file ~ /.*-nat\.c/ {
    fail("read_register_gen in target")
}

BEGIN { doc["read_register_bytes"] = "\
The function read_register_bytes() should be avoided.  Typically \
read_register_gen() can be used.  There are unfortunatly still one or \
two cases where read_register_bytes() is needed that need to be fixed \
and until that is done, it is not possible to make this an error."
    level["read_register_bytes"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])read_register_bytes[[:blank:]]*\(/ {
    fail("read_register_bytes")
}

BEGIN { doc["write_register_bytes"] = "\
The function write_register_bytes() should be avoided.  Typically \
write_register_gen() can be used.  There are unfortunatly still one or \
two cases where write_register_bytes() is needed that need to be fixed \
and until that is done, it is not possible to make this an error."
    level["write_register_bytes"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])write_register_bytes[[:blank:]]*\(/ {
    fail("write_register_bytes")
}

BEGIN { doc["registers_fetched"] = "\
registers_fetched() is replaced by supply_register().";
    level["registers_fetched"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])registers_fetched[[:blank:]]*\(/ {
    fail("registers_fetched")
}

BEGIN { doc["generic_get_saved_register"] = "\
generic_get_saved_register() is replaced by \
generic_unwind_get_saved_register() (which really should be made the \
default).";
    level["generic_get_saved_register"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])generic_get_saved_register[[:blank:]]*\(/ {
    fail("generic_get_saved_register")
}

BEGIN { doc["deprecated"] = "\
Uses a deprecated function or macro.";
    level["DEPRECATED"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])DEPRECATED_/ || \
/(^|[^_[:alnum:]])deprecated_/ {
    fail("deprecated")
}

BEGIN { doc["REGISTER_NAME_ALIAS_HOOK"] = "\
REGISTER_NAME_ALIAS_HOOK() is obsolete.";
    level["REGISTER_NAME_ALIAS_HOOK"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])REGISTER_NAME_ALIAS_HOOK[[:blank:]]*\(/ \
|| /(^|[^_[:alnum:]])REGISTER_NAME_ALIAS_HOOK[[:blank:]]*\(/ {
    fail("REGISTER_NAME_ALIAS_HOOK")
}

BEGIN { doc["STORE_PSEUDO_REGISTER"] = "\
STORE_PSEUDO_REGISTER() is replaced with gdbarch_register_write().";
    level["STORE_PSEUDO_REGISTER"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])STORE_PSEUDO_REGISTER[[:blank:]]*\(/ \
|| /(^|[^_[:alnum:]])set_gdbarch_store_pseudo_register[[:blank:]]*\(/ {
    fail("STORE_PSEUDO_REGISTER")
}

BEGIN { doc["FETCH_PSEUDO_REGISTER"] = "\
FETCH_PSEUDO_REGISTER() is replaced by gdbarch_register_read().";
    level["FETCH_PSEUDO_REGISTER"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])FETCH_PSEUDO_REGISTER[[:blank:]]*\(/ || \
/(^|[^_[:alnum:]])set_gdbarch_fetch_pseudo_register[[:blank:]]*\(/ {
    fail("FETCH_PSEUDO_REGISTER")
}

BEGIN { doc["IS_TRAPPED_INTERNALVAR"] = "\
IS_TRAPPED_INTERNALVAR() is replaced by gdbarch_register_read().";
    level["IS_TRAPPED_INTERNALVAR"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])IS_TRAPPED_INTERNALVAR[[:blank:]]*\(/ {
    fail("IS_TRAPPED_INTERNALVAR")
}

BEGIN { doc["REGISTER_BYTE"] = "\
REGISTER_BYTE and its co-conspirator, registers[] should both be deleted.  \
The successor, computed at run-time, should be local to regcache.c.";
    level["REGISTER_BYTE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_BYTE[[:blank:]]*\(/ {
    fail("REGISTER_BYTE")
}

BEGIN { doc["REGISTER_BYTES"] = "\
REGISTER_BYTES the size of the regcache can be computed at run time.";
    level["REGISTER_BYTES"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_BYTES[[:blank:]]*\(/ {
    fail("REGISTER_BYTES")
}

BEGIN { doc["REGISTER_VIRTUAL_TYPE"] = "\
REGISTER_VIRTUAL_TYPE() should be replaced by a single \
REGISTER_TYPE() function."
    level["REGISTER_VIRTUAL_TYPE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_VIRTUAL_TYPE[[:blank:]]*\(/ {
    fail("REGISTER_VIRTUAL_TYPE")
}

BEGIN { doc["REGISTER_{RAW,VIRTUAL}_SIZE"] = "\
REGISTER_{RAW,VIRTUAL}_SIZE() should be replaced by a single \
REGISTER_SIZE() function that computes the size from \
REGISTER_VIRTUAL_TYPE().";
    level["REGISTER_{RAW,VIRTUAL}_SIZE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_RAW_SIZE[[:blank:]]*\(/ || \
/(^|[^_[:alnum:]])REGISTER_VIRTUAL_SIZE[[:blank:]]*\(/ {
    fail("REGISTER_{RAW,VIRTUAL}_SIZE")
}

BEGIN { doc["MAX_REGISTER_{RAW,VIRTUAL}_SIZE"] = "\
MAX_REGISTER_{RAW,VIRTUAL}_SIZE can be computed at runtime from \
REGISTER_{RAW,VIRTUAL}_SIZE().";
    level["MAX_REGISTER_{RAW,VIRTUAL}_SIZE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])MAX_REGISTER_RAW_SIZE([^_[:alnum:]]|$)/ || \
/(^|[^_[:alnum:]])MAX_REGISTER_VIRTUAL_SIZE([^_[:alnum:]]|$)/ {
    fail("MAX_REGISTER_{RAW,VIRTUAL}_SIZE")
}

BEGIN { doc["[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]"] = "\
MAX_REGISTER_{RAW,VIRTUAL}_SIZE is a function and, hence, can not be \
used to specify the size of an array.";
    level["[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]"] = '$ARI_CODE'
}
/\[[[:blank:]]*MAX_REGISTER_RAW_SIZE[[:blank:]]*\]/ || \
/\[[[:blank:]]*MAX_REGISTER_VIRTUAL_SIZE[[:blank:]]*\]/ {
    fail("[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]")
}

BEGIN { doc["DO_REGISTERS_INFO"] = "\
DO_REGISTERS_INFO() should be replaced by FRAME_REGISTERS_INFO.";
    level["DO_REGISTERS_INFO"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])DO_REGISTERS_INFO[[:blank:]]*\(/ {
    fail("DO_REGISTERS_INFO")
}

BEGIN { doc["REGISTER_CONVERTIBLE"] = "\
REGISTER_CONVERTIBLE() has overloaded semantics.";
    level["REGISTER_CONVERTIBLE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERTIBLE[[:blank:]]*\(/ {
    fail("REGISTER_CONVERTIBLE")
}

BEGIN { doc["REGISTER_CONVERT_TO_RAW"] = "\
REGISTER_CONVERT_TO_RAW() has overloaded semantics.";
    level["REGISTER_CONVERT_TO_RAW"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERT_TO_RAW[[:blank:]]*\(/ {
    fail("REGISTER_CONVERT_TO_RAW")
}

BEGIN { doc["REGISTER_CONVERT_TO_VIRTUAL"] = "\
REGISTER_CONVERT_TO_VIRTUAL() has overloaded semantics.";
    level["REGISTER_CONVERT_TO_VIRTUAL"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERT_TO_VIRTUAL[[:blank:]]*\(/ {
    fail("REGISTER_CONVERT_TO_VIRTUAL")
}

# The totally dreaded FP REGNUM code.

BEGIN { doc["FP_REGNUM"] = "\
FP_REGNUM() is going to be deleted.";
    level["FP_REGNUM"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])FP_REGNUM[[:blank:]]*\(/ {
    fail("FP_REGNUM")
}

BEGIN { doc["TARGET_WRITE_FP"] = "\
TARGET_WRITE_FP() has been deleted.";
    level["TARGET_WRITE_FP"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])TARGET_WRITE_FP[[:blank:]]*\(/ {
    fail("TARGET_WRITE_FP")
}

BEGIN { doc["write_fp"] = "\
write_fp() has been deleted.";
    level["write_fp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])write_fp[[:blank:]]*\(/ {
    fail("write_fp")
}

BEGIN { doc["TARGET_READ_FP"] = "\
TARGET_READ_FP() might be deleted.";
    level["TARGET_READ_FP"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])TARGET_READ_FP[[:blank:]]*\(/ {
    fail("TARGET_READ_FP")
}

BEGIN { doc["read_fp"] = "\
read_fp() might be deleted.";
    level["read_fp"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])read_fp[[:blank:]]*\(/ {
    fail("read_fp")
}

# Print functions: Use versions that either check for buffer overflow
# or safely allocate a fresh buffer.

BEGIN { doc["sprintf"] = "\
sprintf() should be avoided.  Use either xasprintf() or snprintf().";
    level["sprintf"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])sprintf[[:blank:]]*\(/ {
    fail("sprintf")
}

BEGIN { doc["vsprint"] = "\
vsprint() should be avoided.  Use either xvasprint() or vsnprintf().";
    level["vsprint"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])vsprint[[:blank:]]*\(/ {
    fail("vsprint")
}

BEGIN { doc["asprintf"] = "\
asprintf() is deprecated in favour of xasprintf().";
    level["asprintf"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])asprintf[[:blank:]]*\(/ {
    fail("asprintf")
}

BEGIN { doc["vasprintf"] = "\
vasprintf() is deprecated in favour of xvasprintf().";
    fix("vasprintf", "gdb/utils.c", 1)
    level["vasprintf"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])vasprintf[[:blank:]]*\(/ {
    fail("vasprintf")
}

# Memory allocation: malloc(): Use versions that check for NULL memory
# buffers.  gdb/utils.c contains wrappers that call the underlying
# functions.

BEGIN { doc["malloc"] = "\
GDB uses xmalloc() and not malloc()";
    level["malloc"] = '$ARI_REGRESSION';
    fix("malloc", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]])malloc[[:blank:]]*\(/ {
    fail("malloc")
}

BEGIN { doc["calloc"] = "\
GDB uses xcalloc() and not calloc()";
    level["calloc"] = '$ARI_REGRESSION';
    fix("calloc", "gdb/utils.c", 1);
}
/(^|[^_[:alnum:]])calloc[[:blank:]]*\(/ {
    fail("calloc")
}

BEGIN { doc["realloc"] = "\
GDB uses xrealloc() and not realloc()";
    level["realloc"] = '$ARI_REGRESSION';
    fix("realloc", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]])realloc[[:blank:]]*\(/ {
    fail("realloc")
}

BEGIN { doc["free"] = "\
GDB uses xfree() and not free().  xfree() can handle NULL.";
    level["free"] = '$ARI_REGRESSION';
    fix("free", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]>\.])free[[:blank:]]*\(/ {
    fail("free")
}

# Memory allocation: mmalloc(): Use versions that check for NULL memory
# buffers.  gdb/utils.c contains wrappers that call the underlying
# functions.

BEGIN { doc["mmalloc"] = "\
GDB uses xmmalloc() and not mmalloc()";
    level["mmalloc"] = '$ARI_REGRESSION'
    fix("mmalloc", "gdb/utils.c", 4);
}
/(^|[^_[:alnum:]])mmalloc[[:blank:]]*\(/ {
    fail("mmalloc")
}

BEGIN { doc["mcalloc"] = "\
GDB uses xmcalloc() and not mcalloc()";
    level["mcalloc"] = '$ARI_REGRESSION'
    fix("mcalloc", "gdb/utils.c", 2);
}
/(^|[^_[:alnum:]])mcalloc[[:blank:]]*\(/ {
    fail("mcalloc")
}

BEGIN { doc["mrealloc"] = "\
GDB uses xmrealloc() and not mrealloc()";
    level["mrealloc"] = '$ARI_REGRESSION'
    fix("mrealloc", "gdb/utils.c", 2);
}
/(^|[^_[:alnum:]])mrealloc[[:blank:]]*\(/ {
    fail("mrealloc")
}

BEGIN { doc["mfree"] = "\
GDB uses xmfree() and not mfree()";
    level["mfree"] = '$ARI_REGRESSION'
    fix("mfree", "gdb/utils.c", 3);
}
/(^|[^_[:alnum:]>\.])mfree[[:blank:]]*\(/ {
    fail("mfree")
}

# Memory allocation: xmmalloc(): We are trying to eliminate these
# versions and just use simple xmalloc() and obstacks.

BEGIN { doc["xmmalloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
    level["xmmalloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmmalloc[[:blank:]]*\(/ {
    fail("xmmalloc")
}

BEGIN { doc["xmcalloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
    level["xmcalloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmcalloc[[:blank:]]*\(/ {
    fail("xmcalloc")
}

BEGIN { doc["xmrealloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
    level["xmrealloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmrealloc[[:blank:]]*\(/ {
    fail("xmrealloc")
}

BEGIN { doc["xmfree"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
    level["xmfree"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]>\.])xmfree[[:blank:]]*\(/ {
    fail("xmfree")
}

# More generic memory operations

BEGIN { doc["FREEIF"] = "\
GDB uses xfree() and not FREEIF()";
    level["FREEIF"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])FREEIF[[:blank:]]*\(/ {
    fail("FREEIF")
}

BEGIN { doc["MALLOC_INCOMPATIBLE"] = "\
MALLOC_INCOMPATIBLE should be handled by autoconf.";
    level["MALLOC_INCOMPATIBLE"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])MALLOC_INCOMPATIBLE([^_[:alnum:]]|$)/ {
    fail("MALLOC_INCOMPATIBLE")
}

BEGIN { doc["strdup"] = "\
GDB uses xstrdup() and not strdup()";
    level["strdup"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strdup[[:blank:]]*\(/ {
    fail("strdup")
}

BEGIN { doc["strsave"] = "\
strsave() is deprecated in favour of xstrdup() et.al.";
    level["strsave"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strsave[[:blank:]]*\(/ {
    fail("strsave")
}

BEGIN { doc["savestring"] = "\
savestring() needs a rethink.  Should there be a xstrldup() (???).";
    level["savestring"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])savestring[[:blank:]]*\(/ {
    fail("savestring")
}

BEGIN { doc["alloca"] = "\
alloca() is non-portable but its use is tolerated";
    level["alloca"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])alloca[[:blank:]]*\(/ {
    fail("alloca")
}

# String compare functions

BEGIN { doc["STREQ"] = "\
Use ``strcmp() == 0'\'\'' instead of STREQ()."
    level["STREQ"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])STREQ[[:blank:]]*\(/ {
    fail("STREQ")
}

BEGIN { doc["STRCMP"] = "\
Use ``strcmp() == 0'\'\'' instead of STRCMP()"
    level["STRCMP"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])STRCMP[[:blank:]]*\(/ {
    fail("STRCMP")
}

BEGIN { doc["STREQN"] = "\
Use ``strncmp() == 0'\'\'' instead of STREQN()"
    level["STREQN"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])STREQN[[:blank:]]*\(/ {
    fail("STREQN")
}

BEGIN { doc["strncpy"] = "\
Uses strncpy instead of strlcpy (which does not yet exist)";
    level["strncpy"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])strncpy[[:blank:]]*\(/ {
    fail("strncpy")
}

BEGIN { doc["!strcmp"] = "\
Use ``strcmp() == 0'\'\'' rather than ``!strcmp()'\'\''.  Correctly \
understanding ``string-compare equals ...'\'\'' is easier than the \
backward logic of ``Not string-compare'\'\''.";
    level["!strcmp"] = '$ARI_INFO'
}
/\![[:blank:]]*str/ {
    fail("!strcmp")
}

BEGIN { doc["strnicmp"] = "\
GDB uses strncasecmp() and not strnicmp()";
    level["strnicmp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strnicmp[[:blank:]]*\(/ {
    fail("strnicmp")
}

# Boolean expressions and conditionals

BEGIN { doc["FALSE"] = "\
Definitely do not use FALSE in boolean expressions.";
    level["FALSE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])FALSE([^_[:alnum:]]|$)/ {
    fail("FALSE")
}

BEGIN { doc["TRUE"] = "\
Do not try to use TRUE in boolean expressions.";
    level["TRUE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])TRUE([^_[:alnum:]]|$)/ {
    fail("TRUE")
}

BEGIN { doc["false"] = "\
Definitely do not use ``false'\'\'' in boolean expressions.";
    level["false"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])false([^_[:alnum:]]|$)/ {
    fail("false")
}

BEGIN { doc["true"] = "\
Do not try to use ``true'\'\'' in boolean expressions.";
    level["true"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])true([^_[:alnum:]]|$)/ {
    fail("true")
}

BEGIN { doc["if assignment"] = "\
An IF statement'\''s expression contains an assignment.  The GNU coding \
standard discourages this.";
    level["if assignment"] = '$ARI_WARNING'
}
/ if .* = / {
    fail("if assignment")
}

# Typedefs that are either redundant or can be reduced to ``struct
# type *''.

BEGIN { doc["GDB_FILE"] = "\
GDB_FILE is deprecated in favor of ``struct ui_file'\'\''";
    level["GDB_FILE"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])GDB_FILE([^_[:alnum:]]|$)/ {
    fail("GDB_FILE")
}

BEGIN { doc["struct complaint"] = "\
``struct complaint'\'\'' is just nasty and over complex - hashing the \
format string would probably have done the trick";
    level["struct complaint"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])struct complaint([^_[:alnum:]]|$)/ {
    fail("struct complaint")
}

BEGIN { doc["serial_t"] = "\
Change serial_t to ``struct serial'\'\''.";
    level["serial_t"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])serial_t([^_[:alnum:]]|$)/ {
    fail("serial_t")
}

BEGIN { doc["value_ptr"] = "\
Change value_ptr to ``struct value *'\'\''.";
    level["value_ptr"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])value_ptr([^_[:alnum:]]|$)/ {
    fail("value_ptr")
}

BEGIN { doc["tm_print_insn"] = "\
tm_print_insn has been multi-arched.";
    level["tm_print_insn"] = '$ARI_DEPRECATED'
}
/tm_print_insn[[:space:]]*=/ {
    fail("tm_print_insn")
}

BEGIN { doc["goto"] = "\
Please do not use ``goto'\'\''.";
    level["goto"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])goto([^_[:alnum:]]|$)/ {
    fail("goto")
}

BEGIN { doc["label"] = "\
Please do not use labels.";
    level["label"] = '$ARI_INFO'
}
/^[[:space:]]*[[:alpha:]_][[:alnum:]_]*[[:space:]]*:/ \
    && ! /^[[:space:]]*default[[:space:]]*:/ {
    fail("label")
}

BEGIN { doc["codestream"] = "\
Several targets contain a codestream - aka instruction cache.  More than anything \
is is probably caused by the broken target stack.";
    level["codestream"] = '$ARI_INFO'
}
/codestream/ {
    fail("codestream")
}

BEGIN { doc["wrap_"] = "\
Several targets are using a wrapper function found in wrapper.c. \
Unfortunatly, they are hard to debug and contain a bad cast."
    level["wrap_"] = '$ARI_INFO'
}
/wrap_/ {
    fail("wrap_")
}

BEGIN { doc["var_auto_boolean"] = "\
Use the function add_setshow_auto_boolean_cmd() instead of var_auto_boolean.";
    fix("var_auto_boolean", "gdb/cli/cli-decode.c", 1)
    fix("var_auto_boolean", "gdb/cli/cli-decode.h", 1)
    fix("var_auto_boolean", "gdb/cli/cli-setshow.c", 2)
    fix("var_auto_boolean", "gdb/command.h", 1)
    level["var_auto_boolean"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])var_auto_boolean([^_[:alnum:]]|$)/ {
    fail("var_auto_boolean")
}

BEGIN { doc["var_boolean"] = "\
Use the function add_setshow_boolean_cmd() instead of var_boolean.";
    level["var_boolean"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])var_boolean([^_[:alnum:]]|$)/ {
    fail("var_boolean")
}

BEGIN { doc["add_show_from_set"] = "\
See gdb/434. \
The function add_show_from_set() is very i18n unfriendly. \
Create, and then use an equivalent add_setshow_...._cmd()."
    level["add_show_from_set"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])add_show_from_set([^_[:alnum:]]|$)/ {
    fail("add_show_from_set")
}

END {
    # Dump the documentation
    for (bug in doc) {
	if (! (bug in total)) {
	    total[bug] = 0
	}
    }
    for (bug in doc) {
	# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
	print bug ":" total[bug] ":" level[bug] ":" doc[bug] >> "'${wwwdir}'/ari.source.doc"
    }
}'
fi


if ${check_doschk_p} && test -d "${srcdir}"
then
    echo "`date`: Checking for doschk" 1>&2
    rm -f "${wwwdir}"/ari.doschk.*
    fnchange_lst="${srcdir}"/gdb/config/djgpp/fnchange.lst
    fnchange_sed="${wwwdir}"/ari.doschk.sed
    # Create fnchange.sed
    sed -e 's;@[^@]*@[/]*\([^ ]*\) @[^@]*@[/]*\([^ ]*\);s,\1,\2,;' \
	< "${fnchange_lst}" > "${fnchange_sed}"
    # Do the raw analysis
    ( cd "${srcdir}" && find * \
	-name '*.info-[0-9]*' -prune \
	-o -name tcl -prune \
	-o -name itcl -prune \
	-o -name tk -prune \
	-o -name libgui -prune \
	-o -name tix -prune \
	-o -name dejagnu -prune \
	-o -name expect -prune \
	-o -type f -print ) | sed -f ${fnchange_sed} \
    | doschk > ${wwwdir}/ari.doschk.out
    # Magic to map ari.doschk.out to ari.doschk.bug goes here
    $AWK < ${wwwdir}/ari.doschk.out > ${wwwdir}/ari.doschk.bug '
BEGIN {
    state = 1;
    invalid_dos = state++; bug[invalid_dos] = "invalid dos";  level[invalid_dos] = '$ARI_INFO';
    same_dos = state++;    bug[same_dos] = "DOS";             level[same_dos] = '$ARI_REGRESSION';
    same_sysv = state++;   bug[same_sysv] = "SysV";           level[same_sysv] = '$ARI_INFO';
    long_sysv = state++;   bug[long_sysv] = "long SysV";      level[long_sysv] = '$ARI_INFO';
    internal = state++;    bug[internal] = "internal doschk"; level[internal] = '$ARI_INFO';
    state = 0;
    DOCFILE = "'"${wwwdir}/ari.doschk.doc"'"
}
/^$/ { state = 0; next; }
/^The .* not valid DOS/     { state = invalid_dos; next; }
/^The .* same DOS/          { state = same_dos; next; }
/^The .* same SysV/         { state = same_sysv; next; }
/^The .* too long for SysV/ { state = long_sysv; next; }
/^The .* /                  { state = internal; next; }

NF == 3 { name = $1 ; file = $3 }
NF == 1 { file = $1 }
NF == 0 { next }

state == same_dos || state == same_sysv {
    BUG = bug[state] " dup " name 
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    print BUG ":1:" level[state] ":" file ":0"
    bug_count[BUG] += 1
    bug_level[BUG] = level[state]
    bug_doc[BUG] = "\
The name " name " resolves to duplicate files on a " bug[state] " system.  \
For DOS, this can be fixed by modifying the file fnchange.lst."
    next
}
{
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    BUG = bug[state]
    print BUG ":1:" level[state] ":" file ":0"
    bug_count[BUG] += 1
    bug_level[BUG] = level[state]
    bug_doc[BUG] = "DOSCHK reports a " bug[state] " problem"
}
END {
    for (BUG in bug_count) {
	# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
	print BUG ":" bug_count[BUG] ":" bug_level[BUG] ":" bug_doc[BUG] >> DOCFILE
    }
}
'
fi



if ${check_werror_p} && test -d "${srcdir}"
then
    echo "`date`: Checking Makefile.in for non- -Werror rules"
    rm -f ${wwwdir}/ari.werror.*
    $AWK < "${srcdir}/${project}/Makefile.in" > ${wwwdir}/ari.werror.bug '
BEGIN {
    level = '$ARI_WARNING'
    count = 0
}
/^[-_[:alnum:]]+\.o:/ {
    file = gensub(/.o:.*/, "", 1) ".c"
}
/\$\(CC\).*\$\(INTERNAL_WARN_CFLAGS\)/ {
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    print "no -Werror:1:" level ":" file ":0"
    count++
}
END {
    # ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
    print "no -Werror:" count ":" level ":\
The file has compiler warnings and is not being compiled with -Werror" \
    >> "'"${wwwdir}/ari.werror.doc"'"
}
'
fi



# print_toc LEVEL LO_LEVEL HI_LEVEL TITLE [MIN_COUNT]

# Print a table of contents containing the bugs in the range [LO_LEVEL
# .. HI_LEVEL].  If the bug has an error-count >= MIN_COUNT include a
# link into the error table and include the error in the output.  If
# MIN_COUNT is less than zero, don't bother printing any links but
# still print all errors.  MIN_COUNT defaults to 0/-1 depending on
# LEVEL.

print_toc ()
{
    level=$1 ; shift

    lo_level="$1" ; shift
    hi_level="$1" ; shift

    echo "<p>" >> ${newari}
    echo "<h3>$1</h3>" >> ${newari} ; shift
    cat >> ${newari}

    if [ $# -gt 0 ]
    then
	min_count=$1 ; shift
    elif [ $level -ge $hi_level ]
    then
	min_count=0
    else
	min_count=-1
    fi

    cat >> ${newari} <<EOF
<p>
<table>
<tr><th align=left>BUG</th><th>Total</th><th align=left>Description</th></tr>
EOF
    # ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
    cat ${wwwdir}/ari.*.doc \
    | sort -u \
    | sort -t: +1rn -2 +0d \
    | $AWK >> ${newari} '
BEGIN {
    FS=":"
    LO_LEVEL = '${lo_level}'
    HI_LEVEL = '${hi_level}'
    MIN_COUNT = '${min_count}'
}
{
    # ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
    bug = $1
    count = $2
    level = $3
    doc = $4
    if (level > HI_LEVEL) next
    if (level < LO_LEVEL) next
    if (count < MIN_COUNT) next
    printf "<tr>"
    printf "<th align=left valign=top><a name=\"%s\">", bug
    printf "%s", gensub(/_/, " ", "g", bug)
    printf "</a></th>"
    printf "<td align=right valign=top>"
    if (count > 0 && MIN_COUNT >= 0) {
	printf "<a href=\"#%s,\">%d</a></td>", bug, count
    } else {
	printf "%d", count
    }
    printf "</td>"
    printf "<td align=left valign=top>%s</td>", doc
    printf "</tr>"
    print ""
}'
cat >> ${newari} <<EOF
</table>
<p>
EOF
}


# Merge, generating the ARI tables.
if ${update_web_p}
then
    for level in $ARI_FIRST $ARI_WARNING
    do
	echo "Create the ARI table (level ${level})" 1>&2
	case ${level} in
	    $ARI_FIRST )
		oldari=${wwwdir}/old.html
		ari=${wwwdir}/index.html
		newari=${wwwdir}/new.html
		critical=$ARI_REGRESSION
		;;
	    * )
		oldari=${wwwdir}/old-ari.html
		ari=${wwwdir}/ari.html
		newari=${wwwdir}/new-ari.html
		critical=${level}
		;;
	esac
	rm -f ${newari} ${newari}.gz
	cat <<EOF >> ${newari}
<html>
<head>
<title>A.R. Index for GDB version ${version}</title>
</head>
<body>

<center><h2>A.R. Index for GDB version ${version}<h2></center>

<!-- body, update above using ../index.sh -->

<center><h3>You can not take this seriously!</h3></center>

<center>
Also available:
<a href="../gdb/ari/">most recent branch</a>
|
<a href="../gdb/current/ari/">current</a>
|
<a href="../gdb/download/ari/">last release</a>
</center>

<center>
Last updated: `date -u`
</center>

<center>
Input files: `( cd ${wwwdir} && ls ari.*.bug ) | while read bug
do
    echo "<a href=\"${bug}\">${bug}</a>"
done`
</center>
EOF

	print_toc ${level} 0 ${critical} Critical 1 <<EOF
(or things that have been eliminated)
EOF

	# Remember to prune the dir prefix from projects files
	cat ${wwwdir}/ari.*.bug \
	    | sort -t: +3 \
	    | sed -e "s,:${project}/,:," \
	    | $AWK >> ${newari} '
function print_heading (where_i) {
    print ""
    print "<tr border=1>"
    print "<th align=left>File</th>"
    print "<th></th>"
    print "<th align=left><em>Total</em></th>"
    print "<th></th>"
    for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
	bug = i2bug[bug_i];
	printf "<th>"
	printf "<a name=\"%s,\">&nbsp;</a>", bug
	printf "<a href=\"#%s\">", bug
	printf "%s", gensub(/_/, " ", "g", bug)
	printf "</a>\n"
	printf "</th>\n"
    }
    print "<th></th>"
    print "<th align=left><em>Total</em></th>"
    print "<th></th>"
    print "<th align=left>File</th>"
    print "</tr>"
}
function print_totals (where) {
    print "<th align=left><em>Totals</em></th>"
    print "<th></th>"
    print "<th align=right><em>" total "</em></th>"
    print "<th></th>";
    for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
	bug = i2bug[bug_i];
	printf "<th align=right>"
	printf "<a name=\"%s,%s\">&nbsp;</a>", bug, where
	printf "<em>"
	printf "<a href=\"#%s\">%d</a>", bug, bug_total[bug]
	printf "</em>";
	printf "<a href=\"#%s,%s\">^</a>", bug, prev_file[bug, where]
	printf "<a href=\"#%s,%s\">v</a>", bug, next_file[bug, where]
	printf "</th>";
	print ""
    }
    print "<th></th>"
    print "<th align=right><em>" total "</em></th>";
    print "<th></th>"
    print "<th align=left><em>Totals</em></th>"
    print "</tr>"
}
BEGIN {
    FS = ":"
    LEVEL = '${level}'
    nr_file = 0;
    nr_bug = 0;
    # Dummy entries for first/last
    i2file[0] = 0
    i2file[-1] = -1
    i2bug[0] = 0
    i2bug[-1] = -1
}
{
    # ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
    bug = $1
    count = $2
    level = $3
    file = $4
    line = $5
    # Interested in this
    if (level > LEVEL) next
    # Totals
    if (count != 0) {
	if (level < LEVEL) {
	    bold[bug, file] = "th"
	} else {
	    bold[bug, file] = "td"
	}
	db[bug, file] += count
	bug_total[bug] += count
	file_total[file] += count
	total += count
    }
    # Map file <-> index
    if (! (file in file2i)) {
	nr_file++;
	i2file[nr_file] = file;
	file2i[file] = nr_file;
    };
    # Map bug <-> index
    if (! (bug in bug2i)) {
	nr_bug++;
	i2bug[nr_bug] = bug;
	bug2i[bug] = nr_bug;
    }
}
END {

    # Construct a table of next/prev

    # For all the bugs, create a cycle that goes to the prev / next file.
    for (bug in bug2i) {
	prev = 0
	prev_file[bug, 0] = -1
	next_file[bug, -1] = 0
	for (file_i = 1; file_i <= nr_file; file_i++) {
	    file = i2file[file_i]
	    if ((bug, file) in db) {
		prev_file[bug, file] = prev
		next_file[bug, prev] = file
		prev = file
	    }
	}
	prev_file[bug, -1] = prev
	next_file[bug, prev] = -1
    }

    # For all the files, create a cycle that goes to the prev / next bug.
    for (file in file2i) {
	prev = 0
	prev_bug[0, file] = -1
	next_bug[-1, file] = 0
	for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
	    bug = i2bug[bug_i]
	    if ((bug, file) in db) {
		prev_bug[bug, file] = prev
		next_bug[prev, bug] = bug
		prev = bug
	    }
	}
	prev_bug[-1, file] = prev
	next_bug[prev, file] = -1
    }

    print "<table border=1 cellspacing=0>"
    print "<tr></tr>"
    print_heading(0);
    print "<tr></tr>"
    print_totals(0);
    print "<tr></tr>"

    for (file_i = 1; file_i <= nr_file; file_i++) {
	file = i2file[file_i];
	print ""
	print "<tr>"
	print "<th align=left>" file "</th>"
	print "<th></th>"
	print "<th align=right>" file_total[file] "</th>"
	print "<th></th>"
	for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
	    bug = i2bug[bug_i];
	    if ((bug, file) in db) {
		printf "<td align=right>"
		printf "<a name=\"%s,%s\">&nbsp;</a>", bug, file
		#printf "<a href=\"#%s,%s\">", bug, next_file[bug, file]
		printf "<a href=\"#%s\">%d</a>", bug, db[bug, file]
		printf "<a href=\"#%s,%s\">^</a>", bug, prev_file[bug, file]
		printf "<a href=\"#%s,%s\">v</a>", bug, next_file[bug, file]
		printf "</td>"
		print ""
	    } else {
		print "<td>&nbsp;</td>"
		#print "<td></td>"
	    }
	}
	print "<th></th>"
	print "<th align=right>" file_total[file] "</th>"
	print "<th></th>"
	print "<th align=left>" file "</th>"
	print "</tr>"
    }

    print "<tr></tr>"
    print_totals(-1)
    print "<tr></tr>"
    print_heading(-1);
    print "<tr></tr>"
    print ""
    print "</table>"
    print ""
}
'
	echo "<hr>" >> ${newari}

	print_toc ${level} $ARI_DEPRECATED $ARI_DEPRECATED Deprecated <<EOF
(or mechanisms that have been replaced with something better,
simpler, cleaner)
EOF

	echo "<hr>" >> ${newari}

	print_toc ${level} $ARI_CODE $ARI_CODE Coding <<EOF
(or things that can cause portability, readability, or coding standard
problems)
EOF

	echo "<hr>" >> ${newari}

	print_toc ${level} $ARI_WARNING $ARI_WARNING Warnings <<EOF
(or things that are thought to a problem and will likely either be
added to Deprecated or Coding)
EOF

	echo "<hr>" >> ${newari}

	print_toc ${level} $ARI_INFO $ARI_INFO Info <<EOF
(or things that, er mostly, no one is even seriously considering)
EOF

	echo "<hr>" >> ${newari}

	print_toc ${level} $ARI_REGRESSION $ARI_REGRESSION Fixed <<EOF
(or things that have been eliminated - unless they regressed, sigh)
EOF

	cat >> ${newari} <<EOF
<!-- /body, update below using ../index.sh -->
</body>
</html>
EOF

	for i in . .. ../..
	do
	    x=${wwwdir}/${i}/index.sh
	    if test -x $x
	    then
		$x ${newari}
		break
	    fi
	done

	gzip -c -v -9 ${newari} > ${newari}.gz

	cp ${ari} ${oldari}
	cp ${ari}.gz ${oldari}.gz
	cp ${newari} ${ari}
	cp ${newari}.gz ${ari}.gz

    done # level
fi # update_web_p

# ls -l ${wwwdir}

exit 0

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]