Sorry, I goofed on that last patch- corrected version (including rx.h this
time):
[josh-002.patch]
This patch rolls up all my current outstanding patches.
- add makefile target and script to test for external libc dependencies
- fix return values in hash and array PMCs (returning 0 in a void func)
- remove unnecessary data pointer <=> function pointer conversions
outside of the JIT code.
- move the definition of the "INLINE" macro out of the rx header and make
available for general use on C++ compilers and gcc.
- remove a few unused variables
--Josh
Index: Makefile.in
===================================================================
RCS file: /home/perlcvs/parrot/Makefile.in,v
retrieving revision 1.133
diff -u -r1.133 Makefile.in
--- Makefile.in 17 Feb 2002 02:46:59 -0000 1.133
+++ Makefile.in 18 Feb 2002 03:25:56 -0000
@@ -153,6 +153,13 @@
$(TEST_PROG): test_main$(O) $(GEN_HEADERS) $(O_FILES) lib/Parrot/OpLib/core.pm
lib/Parrot/PMC.pm
$(LD) ${ld_out}$(TEST_PROG) $(LDFLAGS) $(O_FILES) test_main$(O) $(C_LIBS)
+lib_deps_object: $(O_FILES)
+ $(PERL) lib_deps.pl object $(O_FILES)
+
+lib_deps_source: $(GENERAL_H_FILES)
+ $(PERL) lib_deps.pl source all_source
+
+lib_deps: lib_deps_object lib_deps_source
###############################################################################
#
Index: core.ops
===================================================================
RCS file: /home/perlcvs/parrot/core.ops,v
retrieving revision 1.95
diff -u -r1.95 core.ops
--- core.ops 16 Feb 2002 04:38:14 -0000 1.95
+++ core.ops 18 Feb 2002 03:25:57 -0000
@@ -2227,22 +2227,22 @@
inline op save(in INT) {
INTVAL i = $1;
- stack_push(interpreter, interpreter->user_stack, &i, STACK_ENTRY_INT, NULL);
+ stack_push(interpreter, interpreter->user_stack, &i, STACK_ENTRY_INT,
+STACK_CLEANUP_NULL);
goto NEXT();
}
inline op save(in NUM) {
- stack_push(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_FLOAT, NULL);
+ stack_push(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_FLOAT,
+STACK_CLEANUP_NULL);
goto NEXT();
}
inline op save(in PMC) {
- stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_PMC, NULL);
+ stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_PMC,
+STACK_CLEANUP_NULL);
goto NEXT();
}
inline op save(in STR) {
- stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_STRING, NULL);
+ stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_STRING,
+STACK_CLEANUP_NULL);
goto NEXT();
}
@@ -2339,7 +2339,7 @@
=cut
inline op bsr (in INT) {
- stack_push(interpreter, interpreter->control_stack, expr NEXT(),
STACK_ENTRY_DESTINATION, NULL);
+ stack_push(interpreter, interpreter->control_stack, expr NEXT(),
+STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
goto OFFSET($1);
}
Index: embed.c
===================================================================
RCS file: /home/perlcvs/parrot/embed.c,v
retrieving revision 1.10
diff -u -r1.10 embed.c
--- embed.c 15 Feb 2002 02:30:02 -0000 1.10
+++ embed.c 18 Feb 2002 03:25:57 -0000
@@ -129,7 +129,7 @@
pf = PackFile_new();
- if(!PackFile_unpack(interpreter, pf, program_code, (unsigned)program_size) ) {
+ if(!PackFile_unpack(interpreter, pf, (opcode_t*)program_code,
+(unsigned)program_size) ) {
fprintf(stderr, "Parrot VM: Can't unpack packfile %s.\n", filename);
return NULL;
}
Index: interpreter.c
===================================================================
RCS file: /home/perlcvs/parrot/interpreter.c,v
retrieving revision 1.70
diff -u -r1.70 interpreter.c
--- interpreter.c 16 Feb 2002 04:38:14 -0000 1.70
+++ interpreter.c 18 Feb 2002 03:25:58 -0000
@@ -88,7 +88,7 @@
*/
static void * prederef_oplib_handle = NULL;
-static oplib_init_f prederef_oplib_init = NULL;
+static oplib_init_f prederef_oplib_init = (oplib_init_f)NULLfunc;
static op_lib_t * prederef_oplib = NULL;
static INTVAL prederef_op_count = 0;
static op_info_t * prederef_op_info = NULL;
@@ -195,7 +195,7 @@
Parrot_dlclose(prederef_oplib_handle);
prederef_oplib = NULL;
- prederef_oplib_init = NULL;
+ prederef_oplib_init = (oplib_init_f)NULLfunc;
prederef_oplib_handle = NULL;
}
@@ -466,8 +466,8 @@
/* Initialize interpreter's flags */
interpreter->flags = flags;
- interpreter->warns = mem_sys_allocate(sizeof(struct warnings_t));
- PARROT_WARNINGS_off(interpreter, PARROT_WARNINGS_ALL_FLAG);
+ interpreter->warns = mem_sys_allocate(sizeof(struct warnings_t));
+ PARROT_WARNINGS_off(interpreter, PARROT_WARNINGS_ALL_FLAG);
interpreter->pmc_count = 0;
interpreter->string_count = 0;
Index: key.c
===================================================================
RCS file: /home/perlcvs/parrot/key.c,v
retrieving revision 1.19
diff -u -r1.19 key.c
--- key.c 11 Feb 2002 17:59:11 -0000 1.19
+++ key.c 18 Feb 2002 03:25:59 -0000
@@ -121,7 +121,7 @@
UNUSED (interpreter);
key->size = 0;
- key->keys = 0;
+ key->keys = NULL;
return key;
}
Index: misc.c
===================================================================
RCS file: /home/perlcvs/parrot/misc.c,v
retrieving revision 1.11
diff -u -r1.11 misc.c
--- misc.c 15 Feb 2002 02:30:02 -0000 1.11
+++ misc.c 18 Feb 2002 03:25:59 -0000
@@ -277,6 +277,7 @@
info.phase = PHASE_WIDTH;
goto AGAIN;
}
+ break;
case PHASE_WIDTH:
switch (ch) {
@@ -301,6 +302,7 @@
info.phase = PHASE_PREC;
goto AGAIN;
}
+ break;
case PHASE_PREC:
switch (ch) {
@@ -321,6 +323,7 @@
info.phase = PHASE_TYPE;
goto AGAIN;
}
+ break;
case PHASE_TYPE:
switch (ch) {
Index: ops2c.pl
===================================================================
RCS file: /home/perlcvs/parrot/ops2c.pl,v
retrieving revision 1.17
diff -u -r1.17 ops2c.pl
--- ops2c.pl 14 Feb 2002 19:33:05 -0000 1.17
+++ ops2c.pl 18 Feb 2002 03:25:59 -0000
@@ -187,7 +187,7 @@
print SOURCE @op_func_table;
print SOURCE <<END_C;
- NULL
+ (op_func${suffix}_t)0 /* NULL function pointer */
};
Index: packfile.c
===================================================================
RCS file: /home/perlcvs/parrot/packfile.c,v
retrieving revision 1.25
diff -u -r1.25 packfile.c
--- packfile.c 15 Feb 2002 02:30:02 -0000 1.25
+++ packfile.c 18 Feb 2002 03:26:01 -0000
@@ -1328,7 +1328,7 @@
break;
default:
- fprintf(stderr, "PackFile_Constant_clear: Unrecognized type '%c' during
unpack!\n", (int) type);
+ fprintf(stderr, "PackFile_Constant_clear: Unrecognized type '%c' during
+unpack!\n", (char) type);
return 0;
break;
}
@@ -1584,7 +1584,6 @@
void
PackFile_Constant_pack(struct PackFile_Constant * self, opcode_t * packed) {
opcode_t * cursor;
- FLOATVAL * nv_ptr;
char * charcursor;
size_t i;
opcode_t padded_size;
@@ -1729,7 +1728,7 @@
case PFC_STRING:
printf(" [ 'PFC_STRING', {\n");
- printf(" FLAGS => 0x%04lx,\n", (long) self->string->flags);
+ printf(" FLAGS => 0x%04lx,\n", (unsigned long)
+self->string->flags);
printf(" ENCODING => %s,\n",
self->string->encoding->name);
printf(" TYPE => %s,\n",
Index: pdump.c
===================================================================
RCS file: /home/perlcvs/parrot/pdump.c,v
retrieving revision 1.9
diff -u -r1.9 pdump.c
--- pdump.c 16 Feb 2002 04:38:14 -0000 1.9
+++ pdump.c 18 Feb 2002 03:26:01 -0000
@@ -62,7 +62,7 @@
pf = PackFile_new();
- if (!PackFile_unpack(interpreter, pf, packed, packed_size)) {
+ if (!PackFile_unpack(interpreter, pf, (opcode_t*)packed, packed_size)) {
printf( "Can't unpack.\n" );
return 1;
}
Index: stacks.c
===================================================================
RCS file: /home/perlcvs/parrot/stacks.c,v
retrieving revision 1.19
diff -u -r1.19 stacks.c
--- stacks.c 15 Feb 2002 02:30:02 -0000 1.19
+++ stacks.c 18 Feb 2002 03:26:02 -0000
@@ -97,7 +97,7 @@
*/
void
stack_push(struct Parrot_Interp *interpreter, Stack stack,
- void *thing, INTVAL type, void (*cleanup)(Stack_Entry))
+ void *thing, INTVAL type, stack_cleanup_method_t cleanup)
{
Stack_Chunk chunk = stack->prev;
Stack_Entry entry = &chunk->entry[chunk->used];
Index: string.c
===================================================================
RCS file: /home/perlcvs/parrot/string.c,v
retrieving revision 1.46
diff -u -r1.46 string.c
--- string.c 5 Feb 2002 11:41:27 -0000 1.46
+++ string.c 18 Feb 2002 03:26:02 -0000
@@ -151,8 +151,8 @@
const CHARTYPE *type, STRING **dest_ptr) {
STRING *dest;
- CHARTYPE_TRANSCODER transcoder1 = NULL;
- CHARTYPE_TRANSCODER transcoder2 = NULL;
+ CHARTYPE_TRANSCODER transcoder1 = (CHARTYPE_TRANSCODER)NULLfunc;
+ CHARTYPE_TRANSCODER transcoder2 = (CHARTYPE_TRANSCODER)NULLfunc;
char *srcstart;
char *srcend;
char *deststart;
Index: classes/array.pmc
===================================================================
RCS file: /home/perlcvs/parrot/classes/array.pmc,v
retrieving revision 1.12
diff -u -r1.12 array.pmc
--- classes/array.pmc 14 Feb 2002 23:17:21 -0000 1.12
+++ classes/array.pmc 18 Feb 2002 03:26:03 -0000
@@ -189,7 +189,7 @@
PMC* mypmc;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
@@ -226,7 +226,7 @@
PMC* mypmc;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
@@ -261,7 +261,7 @@
PMC* mypmc;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
Index: classes/perlarray.pmc
===================================================================
RCS file: /home/perlcvs/parrot/classes/perlarray.pmc,v
retrieving revision 1.17
diff -u -r1.17 perlarray.pmc
--- classes/perlarray.pmc 16 Feb 2002 00:03:07 -0000 1.17
+++ classes/perlarray.pmc 18 Feb 2002 03:26:03 -0000
@@ -181,7 +181,7 @@
PMC* pmc2;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
@@ -221,7 +221,7 @@
PMC* pmc2;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
@@ -259,7 +259,7 @@
PMC* pmc2;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
Index: classes/perlhash.pmc
===================================================================
RCS file: /home/perlcvs/parrot/classes/perlhash.pmc,v
retrieving revision 1.12
diff -u -r1.12 perlhash.pmc
--- classes/perlhash.pmc 16 Feb 2002 00:03:07 -0000 1.12
+++ classes/perlhash.pmc 18 Feb 2002 03:26:03 -0000
@@ -1,4 +1,4 @@
-/* perlhash.pmc
+ /* perlhash.pmc
* Copyright: (When this is determined...it will go here)
* CVS Info
* $Id: perlhash.pmc,v 1.12 2002/02/16 00:03:07 simon Exp $
@@ -173,7 +173,7 @@
PMC* pmc2;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
@@ -215,7 +215,7 @@
PMC* pmc2;
if (!key) {
- return 0;
+ return;
}
kp = (key->keys)[0];
Index: include/parrot/parrot.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/parrot.h,v
retrieving revision 1.25
diff -u -r1.25 parrot.h
--- include/parrot/parrot.h 8 Feb 2002 11:42:13 -0000 1.25
+++ include/parrot/parrot.h 18 Feb 2002 03:26:04 -0000
@@ -73,6 +73,26 @@
typedef void* BIGINT;
typedef void* BIGFLOAT;
+/* define some shortcuts for dealing with function pointers */
+/* according to ANSI C, casting between function and non-function pointers is
+ * no good. So we should use "funcptr_t" in place of void* when dealing with
+ * function pointers and NULLfunc in place of NULL */
+typedef void (*funcptr_t)(void);
+#define NULLfunc (funcptr_t)0
+
+/* Provide support for inline keyword where available. Just make sure to use
+ * "INLINE" instead and it will DTRT. */
+#ifdef __cplusplus
+ #define INLINE inline
+#else
+ #ifdef __GNUC__
+ #define INLINE __inline__
+ #else
+ #define INLINE
+ #endif
+#endif
+
+
/* define a macro to acknowledge an unused argument, and silence a "helpful"
compiler warning. gcc will emit a warning on an empty if body unless {} is
used to make an empty block. */
Index: include/parrot/rx.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/rx.h,v
retrieving revision 1.10
diff -u -r1.10 rx.h
--- include/parrot/rx.h 20 Jan 2002 22:17:34 -0000 1.10
+++ include/parrot/rx.h 18 Feb 2002 03:26:04 -0000
@@ -66,11 +66,6 @@
rxStack stack;
} rxinfo;
-#if __cplusplus
- #define INLINE inline
-#else
- #define INLINE
-#endif /* __cplusplus */
rxinfo * rx_allocate_info(struct Parrot_Interp *, STRING *);
Index: include/parrot/stacks.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/stacks.h,v
retrieving revision 1.16
diff -u -r1.16 stacks.h
--- include/parrot/stacks.h 10 Jan 2002 23:14:58 -0000 1.16
+++ include/parrot/stacks.h 18 Feb 2002 03:26:04 -0000
@@ -39,6 +39,9 @@
typedef Stack_Chunk Stack;
+typedef void (*stack_cleanup_method_t)(Stack_Entry);
+#define STACK_CLEANUP_NULL (stack_cleanup_method_t)NULLfunc
+
Stack
new_stack(struct Parrot_Interp *);
@@ -53,7 +56,7 @@
void
stack_push(struct Parrot_Interp *, Stack,
- void *thing, INTVAL type, void (*cleanup)(Stack_Entry));
+ void *thing, INTVAL type, stack_cleanup_method_t cleanup);
void *
stack_pop(struct Parrot_Interp *, Stack, void *where, INTVAL type);
Index: io/io_stdio.c
===================================================================
RCS file: /home/perlcvs/parrot/io/io_stdio.c,v
retrieving revision 1.11
diff -u -r1.11 io_stdio.c
--- io/io_stdio.c 28 Jan 2002 04:27:17 -0000 1.11
+++ io/io_stdio.c 18 Feb 2002 03:26:04 -0000
@@ -231,7 +231,6 @@
const void * buffer, size_t len) {
size_t avail;
long wrote;
- ParrotIOLayer * l;
if(len <= 0)
return 0;
Index: io/io_unix.c
===================================================================
RCS file: /home/perlcvs/parrot/io/io_unix.c,v
retrieving revision 1.8
diff -u -r1.8 io_unix.c
--- io/io_unix.c 30 Jan 2002 15:50:30 -0000 1.8
+++ io/io_unix.c 18 Feb 2002 03:26:05 -0000
@@ -108,7 +108,6 @@
UINTVAL mode;
INTVAL oflags, type;
PIOHANDLE fd;
- const char * modeptr;
type = PIO_TYPE_FILE;
mode = DEFAULT_OPEN_MODE;
@@ -183,13 +182,16 @@
ParrotIO * PIO_unix_fdopen(theINTERP, ParrotIOLayer * layer,
PIOHANDLE fd, UINTVAL flags) {
ParrotIO * io;
- UINTVAL oflags, rflags, mode;
+ UINTVAL oflags, mode;
mode = 0;
+#ifdef HAS_HEADER_FCNTL
+ UNITVAL rflags;
+#endif
oflags = flags_to_unix(flags);
/* FIXME - Check file handle flags, validity */
-#ifdef HAD_HEADER_FCNTL
+#ifdef HAS_HEADER_FCNTL
/* Get descriptor flags */
if((rflags = fcntl(fd, F_GETFL, 0)) >= 0) {
/*int accmode = rflags & O_ACCMODE;*/
Index: lib/Parrot/OpTrans/CPrederef.pm
===================================================================
RCS file: /home/perlcvs/parrot/lib/Parrot/OpTrans/CPrederef.pm,v
retrieving revision 1.7
diff -u -r1.7 CPrederef.pm
--- lib/Parrot/OpTrans/CPrederef.pm 16 Feb 2002 04:38:18 -0000 1.7
+++ lib/Parrot/OpTrans/CPrederef.pm 18 Feb 2002 03:26:05 -0000
@@ -25,7 +25,7 @@
#define REL_PC ((size_t)(cur_opcode - interpreter->prederef_code))
#define CUR_OPCODE (interpreter->code->byte_code + REL_PC)
-static inline opcode_t* prederef_to_opcode(struct Parrot_Interp* interpreter,
+static INLINE opcode_t* prederef_to_opcode(struct Parrot_Interp* interpreter,
void** prederef_addr)
{
ssize_t offset_in_ops;
@@ -34,7 +34,7 @@
return (opcode_t*) interpreter->code->byte_code + offset_in_ops;
}
-static inline void** opcode_to_prederef(struct Parrot_Interp* interpreter,
+static INLINE void** opcode_to_prederef(struct Parrot_Interp* interpreter,
opcode_t* opcode_addr)
{
ssize_t offset_in_ops;
--- /dev/null Sat Jul 14 02:37:41 2001
+++ lib_deps.pl Fri Feb 15 00:21:53 2002
@@ -0,0 +1,594 @@
+#!/usr/bin/perl
+
+# This script is intended to give us an idea of what libc functions
+# this build depends upon.
+#
+# It supports two modes of operation, "object" and "source".
+#
+# In "object" mode, it expects a list of all parrot's object files. It runs
+# nm on each and determines what external functions are being called. Note
+# that it assumes a gnu-ish "nm".
+#
+# In "source" mode, it uses a the cxref program
+# (http://www.gedanken.demon.co.uk/cxref/) to extract information from the
+# program source about what functions are being called, what includes are used,
+# etc. This mode is potentially more thorough, but a bit more magical and
+# therefore less conclusive.
+
+use strict;
+use File::Find;
+
+my %defined_in;
+my %ansi_c89_symbol;
+my %ansi_c89_header;
+
+my ($mode, @files) = @ARGV;
+
+if ($mode !~ /^(source|object)$/ || ! @files) {
+ die "Usage: $0 object <object files..>\n" .
+ " $0 source <source files..>\n";
+}
+
+while (<DATA>) {
+ next if /^\s*#/; chomp;
+ my ($symbol, $file) = /(\S+)\s+(\S+)/;
+ $ansi_c89_symbol{$symbol} = $file unless ($symbol eq "UNDEF");
+ push @{$ansi_c89_header{$file}}, $symbol;
+}
+
+if ($mode eq "object") {
+ do_object();
+} else {
+ do_source();
+}
+
+exit(0);
+
+##############################################################################
+
+sub do_source {
+
+ if ($files[0] eq "all_source") {
+ # do a little "find" action for now.
+
+ @files = ();
+ File::Find::find({wanted => sub {
+ /^.*\.[ch]\z/s &&
+ push @files, $File::Find::name;
+ }}, '.');
+ }
+
+ # note: need to run this a second time so the database is built.
+ # should just use the build process to do it the first time.
+ my $cmd = "cxref -raw -Iinclude -xref @files";
+ print "Running cxref (pass 1)\n";
+ system("$cmd > /dev/null 2>/dev/null");
+ print "Running cxref (pass 2)\n";
+ open(F, "$cmd 2>/dev/null|")
+ || die "Can't run $cmd.\n";
+
+ my %external_calls;
+ my %internal_calls;
+ my %variable_visible;
+ my %system_include;
+ my ($file, $function, $variable);
+ while (<F>) {
+
+ if (/----------------------------------------/) {
+ undef $file if defined($file);
+ next;
+ }
+
+ if (/^INCLUDES : '(.*)' \[System file\]/) {
+ next if ($1 =~ /^include\//);
+ $system_include{$1}{$file}++;
+ next;
+ }
+
+ if (! $file && /^FILE : '(.*)'$/) {
+ $file = $1;
+ next;
+ }
+
+ # skip anything between files.
+ next unless $file;
+
+ # beginning of function block
+ if (/FUNCTION : (.*) \[(.*)\]/) {
+ $function = $1;
+ my $function_scope = $2;
+
+ next;
+ }
+
+ # end of function block
+ if ($function && /^\s*$/) {
+ undef $function;
+ next;
+ }
+
+ # beginning of variable block
+ if (/VARIABLE : (.*) \[(.*)\]/) {
+ $variable = $1;
+ my $variable_scope = $2;
+ if ($variable_scope eq "Local") {
+ $variable_visible{$file}{$1}++;
+ } else {
+ $variable_visible{"ALL"}{$1}++;
+ }
+
+ next;
+ }
+
+ # end of variable block
+ if ($variable && /^\s*$/) {
+ undef $variable;
+ next;
+ }
+
+ if ($function) {
+ if (/Calls (.*) : (.*)/) {
+ # calling another function within parrot.
+ $internal_calls{$1}{"$file:$function"}++
+ unless ($variable_visible{$file}{$1} ||
+ $variable_visible{ALL}{$1});
+ } elsif (/Calls (.*)/) {
+ # calling a function outside of parrot!
+ $external_calls{$1}{"$file:$function"}++
+ unless ($variable_visible{$file}{$1} ||
+ $variable_visible{ALL}{$1});
+ }
+ }
+ }
+
+ close(F);
+
+ # filter out things that start with _. Probably internal libc stuff.
+ my @external_calls = grep { ! /^_/ } sort keys %external_calls;
+ my @internal_calls = grep { ! /^_/ } sort keys %internal_calls;
+ my @non_ansi_external_calls = grep { ! exists($ansi_c89_symbol{$_}) }
+@external_calls;
+
+ printf("Found %d functions which are defined and called within the %d supplied
+source files.\n", scalar(@internal_calls), scalar(@files));
+ printf("Found %d external functions which were called.\n",
+scalar(@external_calls));
+ printf("Of these, %d are not defined by ANSI C89:\n",
+scalar(@non_ansi_external_calls));
+
+ foreach (@non_ansi_external_calls) {
+ print " $_:\n";
+ foreach (sort keys %{$external_calls{$_}}) {
+ print " $_\n";
+ }
+ }
+
+ print "\nThe following non-ansi system includes are used:\n";
+ foreach my $include (sort keys %system_include) {
+ if (! exists($ansi_c89_header{$include})) {
+ print " $include, included by:\n";
+ foreach my $file (sort keys %{$system_include{$include}}) {
+ print " $file\n";
+ }
+ }
+ }
+}
+
+
+sub do_object {
+ foreach my $obj (@files) {
+ open(F, "nm -a $obj|") || die "Can't run nm on $obj\n";
+
+ while(<F>) {
+ chomp;
+
+ my ($type, $symbol) = /^........ (\S) (.*)/;
+
+ if ($type eq 'U') {
+ $defined_in{$symbol} ||= undef;
+ } else {
+ $defined_in{$symbol} = "$obj";
+ }
+ }
+
+ close(F);
+ }
+
+ # omit symbols which begin with _. These are likely to be internal
+ # variables used by libc macros.
+ my @symbols = grep { ! /^_/ } sort keys %defined_in;
+
+ my @external_symbols = sort grep { ! defined($defined_in{$_}) } @symbols;
+ my @internal_symbols = sort grep { defined($defined_in{$_}) } @symbols;
+ my @non_ansi_external_symbols = grep { ! exists($ansi_c89_symbol{$_}) }
+@external_symbols;
+
+ printf("Found %d symbols defined within the %d supplied object files.\n",
+scalar(@internal_symbols), scalar(@files));
+ printf("Found %d external symbols\n", scalar(@external_symbols));
+ printf("Of these, %d are not defined by ANSI C89:\n",
+scalar(@non_ansi_external_symbols));
+
+ print " $_\n" foreach (@non_ansi_external_symbols);
+}
+
+
+__END__
+# The following symbols are available in a C89 Hosted Implementation
+# (not sure if I got this right- it came from a C99 reference, so some 99isms
+# might have slipped in)
+abort stdlib.h
+abs stdlib.h
+acos math.h
+acosf math.h
+acosh math.h
+acoshf math.h
+acoshl math.h
+acosl math.h
+arg complex.h
+asctime time.h
+asin math.h
+asinf math.h
+asinh math.h
+asinhf math.h
+asinhl math.h
+asinl math.h
+atan math.h
+atan2 math.h
+atan2f math.h
+atan2l math.h
+atanf math.h
+atanh math.h
+atanhf math.h
+atanhl math.h
+atanl math.h
+atexit stdlib.h
+atof stdlib.h
+atoi stdlib.h
+atol stdlib.h
+atoll stdlib.h
+bsearch stdlib.h
+cabs complex.h
+cabsf complex.h
+cabsl complex.h
+cacos complex.h
+cacosf complex.h
+cacosh complex.h
+cacoshf complex.h
+cacoshl complex.h
+cacosl complex.h
+calloc stdlib.h
+carg complex.h
+cargf complex.h
+cargl complex.h
+casin complex.h
+casinf complex.h
+casinh complex.h
+casinhf complex.h
+casinhl complex.h
+casinl complex.h
+catan complex.h
+catanf complex.h
+catanh complex.h
+catanhf complex.h
+catanhl complex.h
+catanl complex.h
+cbrt math.h
+cbrtf math.h
+cbrtl math.h
+ccos complex.h
+ccosf complex.h
+ccosh complex.h
+ccoshf complex.h
+ccoshl complex.h
+ccosl complex.h
+ceil math.h
+ceilf math.h
+ceill math.h
+cexp complex.h
+cexpf complex.h
+cexpl complex.h
+cimag complex.h
+cimagf complex.h
+cimagl complex.h
+clearerr stdio.h
+clock time.h
+clog complex.h
+clogf complex.h
+clogl complex.h
+conj complex.h
+conjf complex.h
+conjl complex.h
+copysign math.h
+copysignf math.h
+copysignl math.h
+cos math.h
+cosf math.h
+cosh math.h
+coshf math.h
+coshl math.h
+cosl math.h
+cpow complex.h
+cpowf complex.h
+cpowl complex.h
+cproj complex.h
+cprojf complex.h
+cprojl complex.h
+creal complex.h
+crealf complex.h
+creall complex.h
+csin complex.h
+csinf complex.h
+csinh complex.h
+csinhf complex.h
+csinhl complex.h
+csinl complex.h
+csqrt complex.h
+csqrtf complex.h
+csqrtl complex.h
+ctan complex.h
+ctanf complex.h
+ctanh complex.h
+ctanhf complex.h
+ctanhl complex.h
+ctanl complex.h
+ctime time.h
+difftime time.h
+div stdlib.h
+erf math.h
+erfc math.h
+erfcf math.h
+erfcl math.h
+erff math.h
+erfl math.h
+errno errno.h
+exit stdlib.h
+exp math.h
+exp2 math.h
+exp2f math.h
+exp2l math.h
+expf math.h
+expl math.h
+expm1 math.h
+expm1f math.h
+expm1l math.h
+fabs math.h
+fabsf math.h
+fabsl math.h
+fclose stdio.h
+fdim math.h
+fdimf math.h
+fdiml math.h
+feof stdio.h
+ferror stdio.h
+fflush stdio.h
+fgetc stdio.h
+fgetpos stdio.h
+fgets stdio.h
+floor math.h
+floorf math.h
+floorl math.h
+fma math.h
+fmaf math.h
+fmal math.h
+fmax math.h
+fmaxf math.h
+fmaxl math.h
+fmin math.h
+fminf math.h
+fminl math.h
+fmod math.h
+fmodf math.h
+fmodl math.h
+fopen stdio.h
+fpclassify math.h
+fprintf stdio.h
+fputc stdio.h
+fputs stdio.h
+fread stdio.h
+free stdlib.h
+freopen stdio.h
+frexp math.h
+frexpf math.h
+frexpl math.h
+fscanf stdio.h
+fseek stdio.h
+fsetpos stdio.h
+ftell stdio.h
+fwrite stdio.h
+getc stdio.h
+getchar stdio.h
+getenv stdlib.h
+gets stdio.h
+gmtime time.h
+hypot math.h
+hypotf math.h
+hypotl math.h
+ilogb math.h
+ilogbf math.h
+ilogbl math.h
+imag complex.h
+isalnum ctype.h
+isalpha ctype.h
+isblank ctype.h
+iscntrl ctype.h
+isdigit ctype.h
+isfinite math.h
+isgraph ctype.h
+isgreater math.h
+isgreatereq math.h
+isinf math.h
+isless math.h
+islessequal math.h
+islessgreat math.h
+islower ctype.h
+isnan math.h
+isnormal math.h
+isprint ctype.h
+ispunct ctype.h
+isspace ctype.h
+isunordered math.h
+isupper ctype.h
+isxdigit ctype.h
+labs stdlib.h
+ldexp math.h
+ldexpf math.h
+ldexpl math.h
+ldiv stdlib.h
+lgamma math.h
+lgammaf math.h
+lgammal math.h
+llabs stdlib.h
+llrint math.h
+llrintf math.h
+llrintl math.h
+llround math.h
+llroundf math.h
+llroundl math.h
+localeconv locale.h
+localtime time.h
+log math.h
+log10 math.h
+log10f math.h
+log10l math.h
+log1p math.h
+log1pf math.h
+log1pl math.h
+log2 math.h
+log2f math.h
+log2l math.h
+logb math.h
+logbf math.h
+logbl math.h
+logf math.h
+logl math.h
+longjmp setjmp.h
+lrint math.h
+lrintf math.h
+lrintl math.h
+lround math.h
+lroundf math.h
+lroundl math.h
+malloc stdlib.h
+mblen stdlib.h
+mbstowcs stdlib.h
+mbtowc stdlib.h
+memchr string.h
+memcmp string.h
+memcpy string.h
+memmove string.h
+memset string.h
+mktime time.h
+modf math.h
+modff math.h
+modfl math.h
+nan math.h
+nanf math.h
+nanl math.h
+nearbyint math.h
+nearbyintf math.h
+nearbyintl math.h
+nextafter math.h
+nextafterf math.h
+nextafterl math.h
+nexttoward math.h
+nexttowardf math.h
+nexttowardl math.h
+perror stdio.h
+pow math.h
+printf stdio.h
+putc stdio.h
+putchar stdio.h
+puts stdio.h
+qsort stdlib.h
+raise signal.h
+rand stdlib.h
+real complex.h
+realloc stdlib.h
+remainder math.h
+remainderf math.h
+remainderl math.h
+remove stdio.h
+remquo math.h
+remquof math.h
+remquol math.h
+rename stdio.h
+rewind stdio.h
+rint math.h
+rintf math.h
+rintl math.h
+round math.h
+roundf math.h
+roundl math.h
+scalbln math.h
+scalblnf math.h
+scalblnl math.h
+scalbn math.h
+scalbnf math.h
+scalbnl math.h
+scanf stdio.h
+setbuf stdio.h
+setlocale locale.h
+setvbuf stdio.h
+signal signal.h
+signbit math.h
+sin math.h
+sinf math.h
+sinh math.h
+sinhf math.h
+sinhl math.h
+sinl math.h
+sprintf stdio.h
+sqrt math.h
+sqrtf math.h
+sqrtl math.h
+srand stdlib.h
+sscanf stdio.h
+stderr stdio.h
+stdin stdio.h
+stdout stdio.h
+strcat string.h
+strchr string.h
+strcmp string.h
+strcoll string.h
+strcpy string.h
+strcspn string.h
+strerror string.h
+strftime time.h
+strlen string.h
+strncat string.h
+strncmp string.h
+strncpy string.h
+strpbrk string.h
+strrchr string.h
+strspn string.h
+strstr string.h
+strtod stdlib.h
+strtof stdlib.h
+strtok string.h
+strtol stdlib.h
+strtold stdlib.h
+strtoll stdlib.h
+strtoul stdlib.h
+strtoull stdlib.h
+strxfrm string.h
+system stdlib.h
+tan math.h
+tanf math.h
+tanh math.h
+tanhf math.h
+tanhl math.h
+tanl math.h
+tgamma math.h
+tgammaf math.h
+tgammal math.h
+time time.h
+tmpfile stdio.h
+tmpnam stdio.h
+tolower ctype.h
+toupper ctype.h
+trunc math.h
+truncf math.h
+truncl math.h
+ungetc stdio.h
+vfprintf stdio.h
+vfscanf stdio.h
+vprintf stdio.h
+vscanf stdio.h
+vsprintf stdio.h
+vsscanf stdio.h
+UNDEF assert.h
+UNDEF stdarg.h