mirror of
https://github.com/opnsense/src.git
synced 2026-04-21 14:17:06 -04:00
Remove files that have been removed from vendor branch
This commit is contained in:
parent
8489cc4415
commit
d337ceafd7
83 changed files with 0 additions and 32178 deletions
3757
contrib/gcc/ORDERS
3757
contrib/gcc/ORDERS
File diff suppressed because it is too large
Load diff
|
|
@ -1,18 +0,0 @@
|
|||
Specifying the -g flag to GCC on a RISC iX machine requires upgrading the
|
||||
standard assembler distributed with both RISC iX 1.1 and RISC iX 1.2 with a
|
||||
replacement that is available from Acorn. This version of the assembler is
|
||||
also an order of magnitude faster when assembling to an NFS mounted
|
||||
file-system.
|
||||
|
||||
Users of RISC iX 1.2 and above can obtain a copy of the assembler from the
|
||||
following places:
|
||||
|
||||
1) Via ftp from acorn.acorn.co.uk, directory pub/riscix.
|
||||
|
||||
2) From Acorn Customer Services.
|
||||
|
||||
3) From Granada Microcare.
|
||||
|
||||
Users of versions of RISC iX prior 1.2 should contact Acorn Customer Services;
|
||||
the assembler available on the net will not work with these versions due to
|
||||
changes in the shared libraries and system call numbers.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
Since COFF-encapsulation is obsolete, this may not be needed anymore.
|
||||
|
||||
Return-Path: <jkp@sauna.hut.fi>
|
||||
Date: Mon, 10 Apr 89 10:13:45 +0300
|
||||
From: Jyrki Kuoppala <jkp@sauna.hut.fi>
|
||||
Sender: jkp@sauna.hut.fi
|
||||
To: info-gcc@prep.ai.mit.edu
|
||||
Subject: Kernel fix needed for Altos 3068 to get coff-encapsulation working right
|
||||
Organization: Helsinki University of Technology, Finland.
|
||||
|
||||
Here's a description how to fix a kernel bug in Altos 3068 and get
|
||||
gcc-compiled programs working.
|
||||
|
||||
Author: Jyrki Kuoppala (jkp@cs.hut.fi)
|
||||
Last modified: Mon Apr 10 09:28:40 1989
|
||||
|
||||
There's a bug in the Altos 3068 kernel that causes gcc-compiled
|
||||
programs to fail in certain situations when the machine has a heavy
|
||||
load and also in some other situations. The bug exists at least in
|
||||
SVR 2.2 1.0gT1 and SVR 2.2 1.0e.
|
||||
|
||||
If you have source code to your system, apply the following change to
|
||||
os/exec.c (function gethead):
|
||||
|
||||
Change the lines containing
|
||||
|
||||
u.u_exdata.ux_tstart = sizeof(struct naout) +
|
||||
sizeof(struct filhd) + (ep->ef.nscns * sizeof(struct scnhdr));
|
||||
|
||||
to
|
||||
|
||||
u.u_exdata.ux_tstart = u.u_exdata.ux_txtorg;
|
||||
|
||||
If you only have binary, use sdb to find out the address of the
|
||||
previous lines (on our system it's gethead+0x140) and use your
|
||||
favourite binary editor to change the bytes '3036 0162 fffc 0002 0280
|
||||
0000' to '23f9 01fb f4ca 01fb f4c2 6016'. This may or may not work in
|
||||
your case, depending on the version of the operating system and the
|
||||
phase of the moon.
|
||||
|
||||
Here's what is just before gethead+0x140 to ease finding out the right place:
|
||||
|
||||
0x9224 (gethead+0x122): 23f9 01fb f4ca 01fb f4ce mov.l &0x1fbf4ca.L,&0
|
||||
x1fbf4ce.L []
|
||||
0x922e (gethead+0x12c): 23f9 01fb f4c6 01fb f4ca mov.l &0x1fbf4c6.L,&0
|
||||
x1fbf4ca.L []
|
||||
0x9238 (gethead+0x136): 23f9 01fb f4c2 01fb f4c6 mov.l &0x1fbf4c2.L,&0
|
||||
x1fbf4c6.L []
|
||||
|
||||
Good luck !
|
||||
|
||||
//Jyrki
|
||||
|
||||
jkp@cs.hut.fi
|
||||
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
README.apollo
|
||||
|
||||
Building GCC 2.0 for 680x0 based Apollo systems requires the GNU
|
||||
assembler (GAS) version 1.38.1, with John Vasta's patches applied.
|
||||
|
||||
If you haven't done so yet, get `gas-1.38.1.tar.Z' from your favourite
|
||||
GNU distribution site. Furthermore, get `apollo-gas-1.38.1.diffs'
|
||||
from `labrea.stanford.edu:/pub/gnu', apply the patches, compile and
|
||||
install gas (under the name as). This should go through without any
|
||||
problems.
|
||||
|
||||
After switching into the BSD environment, you can configure GCC 2.0
|
||||
with the command
|
||||
|
||||
% ./configure m68k-apollo-bsd
|
||||
|
||||
The Apollo's `/usr/include/setjmp.h' uses a nonstandard `#options()'
|
||||
construct. You should create a local copy of this file and remove
|
||||
these constructs from the declarations of SIGSETJMP and SIGLONGJMP.
|
||||
|
||||
The Apollo's `/usr/include/sys/types.h' (BSD Version) doesn't allow
|
||||
to test for the definition of `size_t'. This should be fixed by
|
||||
|
||||
#ifndef _SIZE_T
|
||||
#define _SIZE_T
|
||||
typedef long size_t;
|
||||
#endif
|
||||
|
||||
The script `patch-apollo-includes' fixes these two problems, but does
|
||||
_not_ pretend to be a full fledged `fixincludes' for this system.
|
||||
|
||||
If you now follow the standard GCC installation instructions, building
|
||||
GCC 2.0 (including G++ 2.0) should proceed without any problems.
|
||||
|
||||
NB: Debugging is not yet supported for the Apollo. If someone wants
|
||||
to do a _big_ favour to the Apollo users, he/she should consider
|
||||
porting the Binary File Description library (BFD) to the Apollo.
|
||||
This library can be found in the gdb-4.x distributions or in the
|
||||
binutils-1.9x distributions.
|
||||
|
||||
|
||||
|
||||
|
||||
#!/bin/sh
|
||||
# patch-apollo-includes -- fix some (but not all!) Apollo brain damage.
|
||||
|
||||
FILES_TO_PATCH='sys/types.h setjmp.h'
|
||||
|
||||
mkdir sys
|
||||
|
||||
for i in $FILES_TO_PATCH;
|
||||
do
|
||||
cp /bsd4.3/usr/include/$i ./$i
|
||||
done
|
||||
|
||||
patch -b -apollo <<'EOP'
|
||||
*** /bsd4.3/usr/include/sys/types.h Fri Apr 8 20:29:06 1988
|
||||
--- sys/types.h Wed Feb 26 21:17:57 1992
|
||||
***************
|
||||
*** 38,44 ****
|
||||
--- 38,47 ----
|
||||
typedef char * caddr_t;
|
||||
typedef u_long ino_t;
|
||||
typedef long swblk_t;
|
||||
+ #ifndef _SIZE_T
|
||||
+ #define _SIZE_T
|
||||
typedef long size_t;
|
||||
+ #endif
|
||||
typedef long time_t;
|
||||
typedef long dev_t;
|
||||
typedef long off_t;
|
||||
*** /bsd4.3/usr/include/setjmp.h Fri Feb 3 21:40:21 1989
|
||||
--- setjmp.h Sun Feb 23 19:06:55 1992
|
||||
***************
|
||||
*** 24,30 ****
|
||||
--- 24,39 ----
|
||||
#endif
|
||||
|
||||
|
||||
+ #ifdef __GNUC__
|
||||
#ifdef _PROTOTYPES
|
||||
+ extern int sigsetjmp (sigjmp_buf env, int savemask);
|
||||
+ extern void siglongjmp (sigjmp_buf env, int val);
|
||||
+ #else
|
||||
+ extern int sigsetjmp();
|
||||
+ extern void siglongjmp();
|
||||
+ #endif /* _PROTOTYPES */
|
||||
+ #else /* not __GNUC__ */
|
||||
+ #ifdef _PROTOTYPES
|
||||
extern int sigsetjmp(
|
||||
sigjmp_buf env,
|
||||
int savemask
|
||||
***************
|
||||
*** 37,43 ****
|
||||
extern int sigsetjmp() #options(abnormal);
|
||||
extern void siglongjmp() #options(noreturn);
|
||||
#endif /* _PROTOTYPES */
|
||||
!
|
||||
#undef _PROTOTYPES
|
||||
|
||||
#ifdef __cplusplus
|
||||
--- 46,52 ----
|
||||
extern int sigsetjmp() #options(abnormal);
|
||||
extern void siglongjmp() #options(noreturn);
|
||||
#endif /* _PROTOTYPES */
|
||||
! #endif /* not __GNUC__ */
|
||||
#undef _PROTOTYPES
|
||||
|
||||
#ifdef __cplusplus
|
||||
EOP
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
Compiling Fresco with g++
|
||||
-----------------------------
|
||||
|
||||
Fresco is an evolving interface and toolkit for object-oriented
|
||||
graphics. A preliminary version (written in C++) was released
|
||||
with x11r6.
|
||||
|
||||
Previous versions of Fresco have not compiled using g++,
|
||||
partly because of the use of true and false as identifiers.
|
||||
(They are now reserved words in g++, as required by the
|
||||
ANSI/ISO draft standard for C++.)
|
||||
|
||||
If you get x11r6 with public patch #5 or a later version
|
||||
of Fresco, these problems should now be fixed.
|
||||
|
||||
See http://www.faslab.com/fresco/HomePage.html for information
|
||||
on Fresco, including how to get the latest version.
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
This file describes the implementation notes of the GNU C Compiler for
|
||||
the National Semiconductor 32032 chip (and 32000 family).
|
||||
|
||||
The 32032 machine description and configuration file for this compiler
|
||||
is, for NS32000 family machine, primarily machine independent.
|
||||
However, since this release still depends on vendor-supplied
|
||||
assemblers and linkers, the compiler must obey the existing
|
||||
conventions of the actual machine to which this compiler is targeted.
|
||||
In this case, the actual machine which this compiler was targeted to
|
||||
is a Sequent Balance 8000, running DYNIX 2.1.
|
||||
|
||||
The assembler for DYNIX 2.1 (and DYNIX 3.0, alas) does not cope with
|
||||
the full generality of the addressing mode REGISTER RELATIVE.
|
||||
Specifically, it generates incorrect code for operands of the
|
||||
following form:
|
||||
|
||||
sym(rn)
|
||||
|
||||
Where `rn' is one of the general registers. Correct code is generated
|
||||
for operands of the form
|
||||
|
||||
sym(pn)
|
||||
|
||||
where `pn' is one of the special processor registers (sb, fp, or sp).
|
||||
|
||||
An equivalent operand can be generated by the form
|
||||
|
||||
sym[rn:b]
|
||||
|
||||
although this addressing mode is about twice as slow on the 32032.
|
||||
|
||||
The more efficient addressing mode is controlled by defining the
|
||||
constant SEQUENT_ADDRESS_BUG to 0. It is currently defined to be 1.
|
||||
|
||||
Another bug in the assembler makes it impossible to compute with
|
||||
explicit addresses. In order to compute with a symbolic address, it
|
||||
is necessary to load that address into a register using the "addr"
|
||||
instruction. For example, it is not possible to say
|
||||
|
||||
cmpd _p,@_x
|
||||
|
||||
Rather one must say
|
||||
|
||||
addr _x,rn
|
||||
cmpd _p,rn
|
||||
|
||||
|
||||
The ns32032 chip has a number of known bugs. Any attempt to make the
|
||||
compiler unaware of these deficiencies will surely bring disaster.
|
||||
The current list of know bugs are as follows (list provided by Richard
|
||||
Stallman):
|
||||
|
||||
1) instructions with two overlapping operands in memory
|
||||
(unlikely in C code, perhaps impossible).
|
||||
|
||||
2) floating point conversion instructions with constant
|
||||
operands (these may never happen, but I'm not certain).
|
||||
|
||||
3) operands crossing a page boundary. These can be prevented
|
||||
by setting the flag in tm.h that requires strict alignment.
|
||||
|
||||
4) Scaled indexing in an insn following an insn that has a read-write
|
||||
operand in memory. This can be prevented by placing a no-op in
|
||||
between. I, Michael Tiemann, do not understand what exactly is meant
|
||||
by `read-write operand in memory'. If this is referring to the special
|
||||
TOS mode, for example "addd 5,tos" then one need not fear, since this
|
||||
will never be generated. However, is this includes "addd 5,-4(fp)"
|
||||
then there is room for disaster. The Sequent compiler does not insert
|
||||
a no-op for code involving the latter, and I have been informed that
|
||||
Sequent is aware of this list of bugs, so I must assume that it is not
|
||||
a problem.
|
||||
|
||||
5) The 32032 cannot shift by 32 bits. It shifts modulo the word size
|
||||
of the operand. Therefore, for 32-bit operations, 32-bit shifts are
|
||||
interpreted as zero bit shifts. 32-bit shifts have been removed from
|
||||
the compiler, but future hackers must be careful not to reintroduce
|
||||
them.
|
||||
|
||||
6) The ns32032 is a very slow chip; however, some instructions are
|
||||
still very much slower than one might expect. For example, it is
|
||||
almost always faster to double a quantity by adding it to itself than
|
||||
by shifting it by one, even if that quantity is deep in memory. The
|
||||
MOVM instruction has a 20-cycle setup time, after which it moves data
|
||||
at about the speed that normal moves would. It is also faster to use
|
||||
address generation instructions than shift instructions for left
|
||||
shifts less than 4. I do not claim that I generate optimal code for all
|
||||
given patterns, but where I did escape from National's "clean
|
||||
architecture", I did so because the timing specification from the data
|
||||
book says that I will win if I do. I suppose this is called the
|
||||
"performance gap".
|
||||
|
||||
|
||||
Signed bitfield extraction has not been implemented. It is not
|
||||
provided by the NS32032, and while it is most certainly possible to do
|
||||
better than the standard shift-left/shift-right sequence, it is also
|
||||
quite hairy. Also, since signed bitfields do not yet exist in C, this
|
||||
omission seems relatively harmless.
|
||||
|
||||
|
||||
Zero extractions could be better implemented if it were possible in
|
||||
GCC to provide sized zero extractions: i.e. a byte zero extraction
|
||||
would be allowed to yield a byte result. The current implementation
|
||||
of GCC manifests 68000-ist thinking, where bitfields are extracted
|
||||
into a register, and automatically sign/zero extended to fill the
|
||||
register. See comments in ns32k.md around the "extzv" insn for more
|
||||
details.
|
||||
|
||||
|
||||
It should be noted that while the NS32000 family was designed to
|
||||
provide odd-aligned addressing capability for multi-byte data (also
|
||||
provided by the 68020, but not by the 68000 or 68010), many machines
|
||||
do not opt to take advantage of this. For example, on the sequent,
|
||||
although there is no advantage to long-word aligning word data, shorts
|
||||
must be int-aligned in structs. This is an example of another
|
||||
machine-specific machine dependency.
|
||||
|
||||
|
||||
Because the ns32032 is has a coherent byte-order/bit-order
|
||||
architecture, many instructions which would be different for
|
||||
68000-style machines, fold into the same instruction for the 32032.
|
||||
The classic case is push effective address, where it does not matter
|
||||
whether one is pushing a long, word, or byte address. They all will
|
||||
push the same address.
|
||||
|
||||
|
||||
The macro FUNCTION_VALUE_REGNO_P is probably not sufficient, what is
|
||||
needed is FUNCTION_VALUE_P, which also takes a MODE parameter. In
|
||||
this way it will be possible to determine more exactly whether a
|
||||
register is really a function value register, or just one that happens
|
||||
to look right.
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
AIX 3.1 and 3.2 assembler problems
|
||||
|
||||
Specifying the -g flag to GCC on the RS/6000 requires upgrading the
|
||||
standard AIX assembler distributed with AIX 3.1 and versions of AIX
|
||||
3.2 earlier than 3.2.4 with a replacement that is available from IBM.
|
||||
Note that Makefile.in specifies the -g when compiling libgcc2.c.
|
||||
|
||||
You can test for the presence of a fixed assembler by entering the following:
|
||||
% as -u < /dev/null
|
||||
If the command exits normally, the assembler fix already is installed.
|
||||
If the assembler complains that "-u" is an unknown flag, you need to order
|
||||
the fix.
|
||||
|
||||
If you are running AIX 3.1 (lslpp -h bos.obj output reports
|
||||
03.01.0005.XXXX where the 0005 can be any higher number and the XXXX
|
||||
can be any value), call IBM Support at 800-237-5511 and ask for
|
||||
shipment of AIX/6000 fix PTF U403044 for APAR IX22829 (.extern foo
|
||||
conflicts with defining foo).
|
||||
|
||||
If you are running AIX 3.2 but not 3.2.4 or later (lslpp -h bos.obj
|
||||
output reports 03.02.0000.0000), a newer update to the assembler fix
|
||||
is available. Ask for shipment of AIX/6000 fix PTF U416277 for
|
||||
IX32992 (.global prevents detection of duplicate symbol).
|
||||
|
||||
If you are running AIX 3.2.4 or later, you already have the new
|
||||
assembler.
|
||||
|
||||
Any customer can order and get the replacement assembler, and install it on
|
||||
one or more machines. It is available on diskette from IBM Customer Support
|
||||
and from the IBM Internet fix anonymous ftp server (FixDist) at
|
||||
aix.boulder.ibm.com (198.17.57.66).
|
||||
|
||||
If you contact IBM Customer Support, they may also ask you for your customer
|
||||
number. If you do not know it, you will still be able to get the fix, but
|
||||
you will have to be persistent. IBM has corresponding support organizations
|
||||
outside of North America. Call your IBM branch office and ask them to put
|
||||
you in touch with the department that handles fixes for AIX/6000. If that
|
||||
doesn't work, ask for the department that handles software defect support
|
||||
for AIX/6000 and ask for the APAR fix.
|
||||
|
||||
If you use the GNU assembler instead of the system supplied assembler, you need
|
||||
an assembler modified after October 16th, 1995 in order to build the GNU C
|
||||
compiler. This is because the GNU C compiler wants to build a variant of its
|
||||
library, libgcc.a with the -mcpu=common switch to support building programs
|
||||
that can run on either the Power or PowerPC machines.
|
||||
|
||||
|
||||
AIX NLS problems
|
||||
|
||||
AIX on the RS/6000 provides support (NLS) for environments outside of
|
||||
the United States. Compilers and assemblers use NLS to support
|
||||
locale-specific representations of various objects including
|
||||
floating-point numbers ("." vs "," for separating decimal fractions).
|
||||
There have been problems reported where the library linked with GCC does
|
||||
not produce the same floating-point formats that the assembler accepts.
|
||||
If you have this problem, set the LANG environment variable to "C" or
|
||||
"En_US".
|
||||
|
||||
|
||||
AIX 3.2.5 XLC-1.3 problems
|
||||
|
||||
XLC version 1.3.0.0 distributed with AIX 3.2.5 will miscompile jump.c when
|
||||
building the stage1 compiler during the bootstrap process. This will cause
|
||||
GCC to crash and the bootstrap to fail later while compiling libgcc2.c. XLC
|
||||
version 1.3.0.1 or later fixes this problem. XLC-1.3.0.19 also cannot
|
||||
bootstrap GCC so please avoid that release as well. You can obtain
|
||||
XLC-1.3.0.24 by requesting PTF 432238 from IBM, or just ask for the latest
|
||||
release of XLC-1.3.
|
||||
|
||||
There also have been reports of problems bootstrapping GCC with some older
|
||||
releases of xlc-1.2.1, including xlc-1.2.1.8. Newer releases of xlc-1.2.1
|
||||
do not exhibit this problem: xlc-1.2.1.28 is known to bootstrap properly.
|
||||
|
||||
|
||||
AIX 3.2 common-mode support
|
||||
|
||||
AIX common-mode providing transparent support of both the POWER and PowerPC
|
||||
architectures is usable in AIX 3.2.3 and above but an export file and
|
||||
support for hidden export via libc.a will not exist until AIX 4.1. libgcc.a
|
||||
also must be compiled in common-mode. Note that executables generated for
|
||||
the POWER (RIOS1 and RSC) architecture will run directly on systems using
|
||||
the MPC601 chip. Common-mode only improves the performance of a single
|
||||
executable run on both POWER and PowerPC architecture platforms by not using
|
||||
POWER- or PowerPC-specific instructions and eliminating the need to trap to
|
||||
emulation (for POWER instructions run on PowerPC).
|
||||
|
||||
To link a common-mode application prior to AIX 4.1 and run it on a system at
|
||||
AIX level 3.2.3 or above, use the text between the "<>" as an export file
|
||||
(e.g. milli.exp)
|
||||
|
||||
<><><><><><><><><><><>
|
||||
#!
|
||||
__mulh 0x3100
|
||||
__mull 0x3180
|
||||
__divss 0x3200
|
||||
__divus 0x3280
|
||||
__quoss 0x3300
|
||||
__quous 0x3380
|
||||
<><><><><><><><><><><>
|
||||
|
||||
and then link with -Wl,-bI:milli.exp.
|
||||
|
||||
|
||||
AIX 4.1 binder
|
||||
|
||||
Due to changes in the way that GCC invokes the binder (linker) for AIX 4.1,
|
||||
the link step now may produce warnings of duplicate symbols which were not
|
||||
reported before. The assembly files generated by GCC for AIX always have
|
||||
included multiple symbol definitions for certain global variable and
|
||||
function declarations in the original program. The warnings should not
|
||||
prevent the linker from producing a correct library or runnable executable.
|
||||
|
|
@ -1,447 +0,0 @@
|
|||
[This file contains two alternative recipes for compiling X11 with GCC.
|
||||
The first alternative puts libgcc.a into the shared X library; the second
|
||||
does not. Neither alternative works on all kinds of systems.
|
||||
It may be that when using GCC 2.4, both alternatives work okay on
|
||||
relatively recent Sparc systems. The first alternative is likely
|
||||
not to work on a Sun 3 without hardware floating point.]
|
||||
|
||||
How to compile X11R5 (patch level 11) with GCC version 2:
|
||||
|
||||
The patches include support for building the shared libraries with GCC
|
||||
2 on the Sparc and 68k machines. This version includes the necessary
|
||||
parts of libgcc.a in the shared library for X, in case functions in
|
||||
that library need it. Thus the default behavior is now to build
|
||||
everything, including the libraries, with gcc.
|
||||
|
||||
If you build the shared library this way, it may not work with
|
||||
executables made with older versions of GCC (2.3.3 and earlier).
|
||||
If that happens, relink those executables with the latest GCC.
|
||||
IF YOU THINK YOU MIGHT COMPILE X FOR SOLARIS 2, then you really don't
|
||||
need this patch: get /contrib/R5.SunOS5.patch.tar.Z from
|
||||
export.lcs.mit.edu instead. It has everything you need to do the
|
||||
build for Solaris 2, sets you up to everything with GCC, and is
|
||||
backward compatible with Sunos 4.*. Get the the README
|
||||
(/contrib/R5.SunOS5.patch.README at export) for more info.
|
||||
|
||||
If you see undefined symbols _dlopen, _dlsym, or _dlclose when linking
|
||||
with -lX11, compile and link against the file mit/util/misc/dlsym.c in
|
||||
the MIT X11R5 distribution. Alternatively, do dynamic linking
|
||||
by using a non-GNU ld.
|
||||
|
||||
mit/config/Imake.tmpl -- Do not set -fstrength-reduce if we have GCC 2.
|
||||
If -fstrength-reduce (or any other -f option) is a major win, then it
|
||||
will most likely be turned on by -O2 optimization.
|
||||
|
||||
mit/config/sunLib.rules -- If HasGcc and GccVersion > 1 are true, then
|
||||
use gcc -fpic to generate PIC code. Make sure that gcc does not use
|
||||
gas (the GNU assembler) when compiling PIC code; gas does not assemble
|
||||
it correctly.
|
||||
|
||||
***If you have gas installed where gcc uses it by default, you might have
|
||||
to add -B/bin/ to the PositionIndependentCFlags.***
|
||||
|
||||
mit/config/site.def -- Define GccVersion to be 2.
|
||||
|
||||
mit/config/sun.cf -- When compiling with GCC 2, use -O2 optimization.
|
||||
|
||||
mit/config/sunLib.rules -- When compiling with GCC 2, use -fpic for
|
||||
position independent code generation.
|
||||
|
||||
mit/rgb/Imakefile -- No longer need to compile some modules with
|
||||
cc on the Sparc since GCC 2 produces proper -fpcc-struct-return code.
|
||||
|
||||
mit/server/os/Imakefile -- Likewise.
|
||||
|
||||
mit/server/ddx/sun/Imakefile -- When compiling with GCC 2, some modules
|
||||
should be compiled with -fvolatile.
|
||||
|
||||
mit/clients/twm/Imakefile -- Fix bad decls of malloc, realloc in gram.c.
|
||||
|
||||
mit/lib/X/Imakefile -- Make libgcc.a a required lib for libX11.so
|
||||
|
||||
*** mit/clients/twm/Imakefile Mon May 17 22:05:22 1993
|
||||
--- new/clients/twm/Imakefile Mon May 17 22:28:46 1993
|
||||
***************
|
||||
*** 32,41 ****
|
||||
--- 32,48 ----
|
||||
ComplexProgramTarget(twm)
|
||||
InstallNonExecFile(system.twmrc,$(TWMDIR))
|
||||
|
||||
+ #if HasGcc && GccVersion > 1 && defined (SunArchitecture)
|
||||
gram.h gram.c: gram.y
|
||||
yacc $(YFLAGS) gram.y
|
||||
+ sed -e 's/^extern char \*malloc(), \*realloc();//g' y.tab.c >gram.c
|
||||
+ $(MV) y.tab.h gram.h
|
||||
+ #else
|
||||
+ gram.h gram.c: gram.y
|
||||
+ yacc $(YFLAGS) gram.y
|
||||
$(MV) y.tab.c gram.c
|
||||
$(MV) y.tab.h gram.h
|
||||
+ #endif
|
||||
|
||||
clean::
|
||||
$(RM) y.tab.h y.tab.c lex.yy.c gram.h gram.c lex.c deftwmrc.c
|
||||
*** mit/config/Imake.tmpl Mon May 17 22:02:57 1993
|
||||
--- new/config/Imake.tmpl Mon May 17 22:15:06 1993
|
||||
***************
|
||||
*** 500,506 ****
|
||||
--- 500,510 ----
|
||||
#endif
|
||||
#ifndef CcCmd
|
||||
#if HasGcc
|
||||
+ #if GccVersion > 1
|
||||
+ #define CcCmd gcc -fpcc-struct-return
|
||||
+ #else
|
||||
#define CcCmd gcc -fstrength-reduce -fpcc-struct-return
|
||||
+ #endif
|
||||
#else
|
||||
#define CcCmd cc
|
||||
#endif
|
||||
*** mit/config/site.def Mon May 17 22:02:44 1993
|
||||
--- new/config/site.def Mon May 17 22:22:28 1993
|
||||
***************
|
||||
*** 25,31 ****
|
||||
|
||||
#ifdef BeforeVendorCF
|
||||
|
||||
! /* #define HasGcc YES */
|
||||
|
||||
#endif /* BeforeVendorCF */
|
||||
|
||||
--- 25,33 ----
|
||||
|
||||
#ifdef BeforeVendorCF
|
||||
|
||||
! #define HasGcc YES
|
||||
! /* GccVersion > 1 implies building shared libraries with gcc */
|
||||
! #define GccVersion 2
|
||||
|
||||
#endif /* BeforeVendorCF */
|
||||
|
||||
*** mit/config/sun.cf Mon May 17 22:03:02 1993
|
||||
--- new/config/sun.cf Mon May 17 22:24:55 1993
|
||||
***************
|
||||
*** 41,49 ****
|
||||
--- 41,55 ----
|
||||
|
||||
#if HasGcc
|
||||
|
||||
+ #if GccVersion > 1
|
||||
+ #define OptimizedCDebugFlags -O2
|
||||
+ #else
|
||||
+ #define OptimizedCDebugFlags -O
|
||||
#define SharedLibraryCcCmd cc
|
||||
#define ExtraLoadFlags -B/usr/bin/
|
||||
#define AllocateLocalDefines /**/
|
||||
+ #endif
|
||||
+
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
*** mit/config/sunLib.rules Mon May 17 22:02:46 1993
|
||||
--- new/config/sunLib.rules Mon May 17 22:19:06 1993
|
||||
***************
|
||||
*** 23,29 ****
|
||||
--- 23,33 ----
|
||||
#define SharedLibraryLoadFlags -assert pure-text
|
||||
#endif
|
||||
#ifndef PositionIndependentCFlags
|
||||
+ #if defined(HasGcc) && GccVersion > 1
|
||||
+ #define PositionIndependentCFlags -fpic
|
||||
+ #else
|
||||
#define PositionIndependentCFlags -pic
|
||||
+ #endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
*** mit/lib/X/Imakefile Mon May 17 22:05:03 1993
|
||||
--- new/lib/X/Imakefile Mon May 17 22:32:26 1993
|
||||
***************
|
||||
*** 9,14 ****
|
||||
--- 9,31 ----
|
||||
#define MotifBC NO
|
||||
#endif
|
||||
|
||||
+ #if defined(SunArchitecture)
|
||||
+ #if SystemV4
|
||||
+ #if HasGcc
|
||||
+ REQUIREDLIBS= -lgcc -lc
|
||||
+ #else
|
||||
+ REQUIREDLIBS= -lc
|
||||
+ #endif
|
||||
+ #else
|
||||
+ #if HasGcc && GccVersion > 1
|
||||
+ XCOMM Hack to fix gcc 2 ``-nostdlib'' deficiency on SunOS 4.x
|
||||
+ REQUIREDLIBS= `gcc -v 2>&1 | awk '{print $$4}' | sed -e 's/specs$$/libgcc.a/'`
|
||||
+ #else
|
||||
+ REQUIREDLIBS=
|
||||
+ #endif
|
||||
+ #endif
|
||||
+ #endif
|
||||
+
|
||||
#ifndef BuildXimp
|
||||
#define BuildXimp NO
|
||||
#endif
|
||||
*** mit/rgb/Imakefile Mon May 17 22:05:31 1993
|
||||
--- new/rgb/Imakefile Mon May 17 22:25:30 1993
|
||||
***************
|
||||
*** 17,23 ****
|
||||
#if !(defined(SGIArchitecture) || SystemV4)
|
||||
DBMLIB = -ldbm
|
||||
#endif
|
||||
! #if defined(SparcArchitecture) && HasGcc
|
||||
CC = cc
|
||||
CCOPTIONS = /**/
|
||||
EXTRA_LOAD_FLAGS = /**/
|
||||
--- 17,23 ----
|
||||
#if !(defined(SGIArchitecture) || SystemV4)
|
||||
DBMLIB = -ldbm
|
||||
#endif
|
||||
! #if defined(SparcArchitecture) && HasGcc && GccVersion <= 1
|
||||
CC = cc
|
||||
CCOPTIONS = /**/
|
||||
EXTRA_LOAD_FLAGS = /**/
|
||||
*** mit/server/ddx/sun/Imakefile Mon May 17 22:05:57 1993
|
||||
--- new/server/ddx/sun/Imakefile Mon May 17 22:27:23 1993
|
||||
***************
|
||||
*** 43,48 ****
|
||||
--- 43,53 ----
|
||||
LinkFile(sunGX.o,sunGX.o.dist)
|
||||
#endif
|
||||
|
||||
+ #if HasGcc && GccVersion > 1
|
||||
+ SpecialObjectRule(sunCG2C.o,sunCG2C.c,-fvolatile)
|
||||
+ SpecialObjectRule(sunCG2M.o,sunCG2M.c,-fvolatile)
|
||||
+ #endif
|
||||
+
|
||||
sunInitExtMono.o: $(ICONFIGFILES)
|
||||
ObjectFromSpecialSource(sunInitExtMono,../mi/miinitext,-UPEXEXT)
|
||||
ObjectFromSpecialSource(sunInitMono,sunInit,-DMONO_ONLY)
|
||||
*** mit/server/os/Imakefile Mon May 17 22:05:46 1993
|
||||
--- new/server/os/Imakefile Mon May 17 22:26:02 1993
|
||||
***************
|
||||
*** 132,138 ****
|
||||
SpecialObjectRule(osinit.o,$(ICONFIGFILES),$(ADM_DEFINES))
|
||||
SpecialObjectRule(WaitFor.o,$(ICONFIGFILES),$(EXT_DEFINES))
|
||||
SpecialObjectRule(fonttype.o,$(ICONFIGFILES),$(FONT_DEFINES))
|
||||
! #if defined(SparcArchitecture) && HasGcc
|
||||
oscolor.o: $(ICONFIGFILES)
|
||||
$(RM) $@
|
||||
cc -c $(DBM_DEFINES) $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
|
||||
--- 132,138 ----
|
||||
SpecialObjectRule(osinit.o,$(ICONFIGFILES),$(ADM_DEFINES))
|
||||
SpecialObjectRule(WaitFor.o,$(ICONFIGFILES),$(EXT_DEFINES))
|
||||
SpecialObjectRule(fonttype.o,$(ICONFIGFILES),$(FONT_DEFINES))
|
||||
! #if defined(SparcArchitecture) && HasGcc && GccVersion <= 1
|
||||
oscolor.o: $(ICONFIGFILES)
|
||||
$(RM) $@
|
||||
cc -c $(DBM_DEFINES) $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
|
||||
|
||||
|
||||
[This is the older version]
|
||||
|
||||
How to compile X11R5 (patch level 11) with GCC version 2:
|
||||
|
||||
The patches include support for building the shared libraries with GCC 2 on
|
||||
the Sparc and 68k machines.
|
||||
|
||||
NOTE: Such shared libraries built with GCC version 2.3 DID NOT WORK
|
||||
with executables previously linked using Sun CC! This is because
|
||||
neither those executables nor the gcc-compiled shared libraries contain
|
||||
libgcc.a. The shared libraries did work with executables linked using
|
||||
GCC (running the Sun linker, of course) because GCC tells the linker to
|
||||
link in libgcc.a. Because of these limitations the default behavior is
|
||||
to NOT build the shared libraries with gcc.
|
||||
|
||||
Changes in GCC 2.4 seem to have eliminated the problem, and such a
|
||||
shared library now seems work with all executables. If you want the
|
||||
gcc-compiled shared libraries turn on "Gcc2BuildLibs" in site.def. If
|
||||
you try this, please tell bug-gcc@prep.ai.mit.edu whether it works.
|
||||
|
||||
Sun forgot to include a static version of libdl.a with some versions
|
||||
of SunOS (4.1 mainly). If you see undefined symbols _dlopen, _dlsym,
|
||||
or _dlclose when linking with -lX11, compile and link against the file
|
||||
mit/util/misc/dlsym.c in the MIT X11R5 distribution.
|
||||
|
||||
mit/config/Imake.tmpl -- Do not set -fstrength-reduce if we have GCC 2. If
|
||||
-fstrength-reduce (or any other -f option) is a major win, then it will
|
||||
most likely be turned on by -O2 optimization.
|
||||
|
||||
mit/config/sunLib.rules -- If HasGcc2 and Gcc2BuildLibs are defined, then
|
||||
use gcc -fpic to generate PIC code. Make sure that gcc does not use gas (the
|
||||
GNU assembler) when compiling PIC code; gas does not assemble it correctly.
|
||||
If you have gas installed where gcc uses it by default, you might have to add
|
||||
-B/bin/ to the PositionIndependentCFlags.
|
||||
|
||||
mit/config/site.def -- Define HasGcc2 to be YES.
|
||||
|
||||
mit/config/sun.cf -- When compiling with GCC 2, use -O2 optimization.
|
||||
|
||||
mit/rgb/Imakefile -- No longer need to compile some modules with
|
||||
cc on the Sparc since GCC 2 produces proper -fpcc-struct-return code.
|
||||
|
||||
mit/server/os/Imakefile -- Likewise.
|
||||
|
||||
mit/clients/twm/Imakefile -- fix bad decls of malloc, realloc in gram.c.
|
||||
|
||||
*** mit/config/Imake.tmpl.ORIG Tue Dec 31 11:07:56 1991
|
||||
--- mit/config/Imake.tmpl Tue Dec 31 12:30:47 1991
|
||||
***************
|
||||
*** 499,508 ****
|
||||
--- 499,512 ----
|
||||
#define HasGcc NO
|
||||
#endif
|
||||
#ifndef CcCmd
|
||||
+ #if HasGcc2
|
||||
+ #define CcCmd gcc -fpcc-struct-return
|
||||
+ #else
|
||||
#if HasGcc
|
||||
#define CcCmd gcc -fstrength-reduce -fpcc-struct-return
|
||||
#else
|
||||
#define CcCmd cc
|
||||
+ #endif
|
||||
#endif
|
||||
#endif
|
||||
#if HasFortran
|
||||
*** mit/config/sunLib.rules.ORIG Tue Dec 31 11:11:24 1991
|
||||
--- mit/config/sunLib.rules Tue May 5 12:26:12 1992
|
||||
***************
|
||||
*** 23,30 ****
|
||||
--- 23,34 ----
|
||||
#define SharedLibraryLoadFlags -assert pure-text
|
||||
#endif
|
||||
#ifndef PositionIndependentCFlags
|
||||
+ #if defined(HasGcc2) && defined (Gcc2BuildLibs)
|
||||
+ #define PositionIndependentCFlags -fpic
|
||||
+ #else
|
||||
#define PositionIndependentCFlags -pic
|
||||
#endif
|
||||
+ #endif
|
||||
|
||||
/*
|
||||
* InstallSharedLibrary - generate rules to install the shared library.
|
||||
*** mit/config/site.def.ORIG Tue Dec 31 11:13:49 1991
|
||||
--- mit/config/site.def Tue Dec 31 12:02:59 1991
|
||||
***************
|
||||
*** 25,31 ****
|
||||
|
||||
#ifdef BeforeVendorCF
|
||||
|
||||
! /* #define HasGcc YES */
|
||||
|
||||
#endif /* BeforeVendorCF */
|
||||
|
||||
--- 25,33 ----
|
||||
|
||||
#ifdef BeforeVendorCF
|
||||
|
||||
! #define HasGcc YES
|
||||
! #define HasGcc2 YES
|
||||
! /* #define Gcc2BuildLibs YES */
|
||||
|
||||
#endif /* BeforeVendorCF */
|
||||
|
||||
*** mit/config/sun.cf.ORIG Tue Dec 31 11:13:57 1991
|
||||
--- mit/config/sun.cf Tue May 5 12:29:50 1992
|
||||
***************
|
||||
*** 34,42 ****
|
||||
--- 41,61 ----
|
||||
|
||||
#if HasGcc
|
||||
|
||||
+ #if defined(HasGcc2)
|
||||
+ #define OptimizedCDebugFlags -O2
|
||||
+ /* Leave Alone XXX */
|
||||
+ #else
|
||||
+ #define OptimizedCDebugFlags -O
|
||||
#define SharedLibraryCcCmd cc
|
||||
#define ExtraLoadFlags -B/usr/bin/
|
||||
#define AllocateLocalDefines /**/
|
||||
+ #endif
|
||||
+
|
||||
+ #if !defined(Gcc2BuildLibs)
|
||||
+ #define SharedLibraryCcCmd cc
|
||||
+ #define ExtraLoadFlags -B/usr/bin/
|
||||
+ #define AllocateLocalDefines /**/
|
||||
+ #endif
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
*** mit/rgb/Imakefile.ORIG Wed Jan 15 16:43:18 1992
|
||||
--- mit/rgb/Imakefile Thu Jan 2 13:34:09 1992
|
||||
***************
|
||||
*** 17,23 ****
|
||||
#if !(defined(SGIArchitecture) || SystemV4)
|
||||
DBMLIB = -ldbm
|
||||
#endif
|
||||
! #if defined(SparcArchitecture) && HasGcc
|
||||
CC = cc
|
||||
CCOPTIONS = /**/
|
||||
EXTRA_LOAD_FLAGS = /**/
|
||||
--- 17,23 ----
|
||||
#if !(defined(SGIArchitecture) || SystemV4)
|
||||
DBMLIB = -ldbm
|
||||
#endif
|
||||
! #if defined(SparcArchitecture) && HasGcc && !defined(HasGcc2)
|
||||
CC = cc
|
||||
CCOPTIONS = /**/
|
||||
EXTRA_LOAD_FLAGS = /**/
|
||||
*** mit/server/os/Imakefile.ORIG Wed Jan 15 16:46:23 1992
|
||||
--- mit/server/os/Imakefile Wed Jan 15 16:46:48 1992
|
||||
***************
|
||||
*** 132,138 ****
|
||||
SpecialObjectRule(osinit.o,$(ICONFIGFILES),$(ADM_DEFINES))
|
||||
SpecialObjectRule(WaitFor.o,$(ICONFIGFILES),$(EXT_DEFINES))
|
||||
SpecialObjectRule(fonttype.o,$(ICONFIGFILES),$(FONT_DEFINES))
|
||||
! #if defined(SparcArchitecture) && HasGcc
|
||||
oscolor.o: $(ICONFIGFILES)
|
||||
$(RM) $@
|
||||
cc -c $(DBM_DEFINES) $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
|
||||
--- 132,138 ----
|
||||
SpecialObjectRule(osinit.o,$(ICONFIGFILES),$(ADM_DEFINES))
|
||||
SpecialObjectRule(WaitFor.o,$(ICONFIGFILES),$(EXT_DEFINES))
|
||||
SpecialObjectRule(fonttype.o,$(ICONFIGFILES),$(FONT_DEFINES))
|
||||
! #if defined(SparcArchitecture) && HasGcc && !defined(HasGcc2)
|
||||
oscolor.o: $(ICONFIGFILES)
|
||||
$(RM) $@
|
||||
cc -c $(DBM_DEFINES) $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
|
||||
*** 1.1 1992/09/08 19:52:07
|
||||
--- mit/server/ddx/sun/Imakefile 1992/09/08 21:10:22
|
||||
***************
|
||||
*** 43,48 ****
|
||||
--- 43,53 ----
|
||||
LinkFile(sunGX.o,sunGX.o.dist)
|
||||
#endif
|
||||
|
||||
+ #if HasGcc2
|
||||
+ SpecialObjectRule(sunCG2C.o,sunCG2C.c,-fvolatile)
|
||||
+ SpecialObjectRule(sunCG2M.o,sunCG2M.c,-fvolatile)
|
||||
+ #endif
|
||||
+
|
||||
sunInitExtMono.o: $(ICONFIGFILES)
|
||||
ObjectFromSpecialSource(sunInitExtMono,../mi/miinitext,-UPEXEXT)
|
||||
ObjectFromSpecialSource(sunInitMono,sunInit,-DMONO_ONLY)
|
||||
|
||||
*** /tmp/RCSAa24446 Tue Sep 15 12:23:32 1992
|
||||
--- mit/clients/twm/Imakefile Thu Aug 13 18:18:07 1992
|
||||
***************
|
||||
*** 32,41 ****
|
||||
--- 32,48 ----
|
||||
ComplexProgramTarget(twm)
|
||||
InstallNonExecFile(system.twmrc,$(TWMDIR))
|
||||
|
||||
+ #if HasGcc2 && defined (SunArchitecture)
|
||||
gram.h gram.c: gram.y
|
||||
yacc $(YFLAGS) gram.y
|
||||
+ sed -e 's/^extern char \*malloc(), \*realloc();//g' y.tab.c >gram.c
|
||||
+ $(MV) y.tab.h gram.h
|
||||
+ #else
|
||||
+ gram.h gram.c: gram.y
|
||||
+ yacc $(YFLAGS) gram.y
|
||||
$(MV) y.tab.c gram.c
|
||||
$(MV) y.tab.h gram.h
|
||||
+ #endif
|
||||
|
||||
clean::
|
||||
$(RM) y.tab.h y.tab.c lex.yy.c gram.h gram.c lex.c deftwmrc.c
|
||||
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
1998-08-11
|
||||
|
||||
This directory contains the egcs variant of version 0.5.24 of the
|
||||
GNU Fortran compiler (g77). The GNU Fortran compiler is free software.
|
||||
See the file COPYING.g77 for copying permission.
|
||||
|
||||
Currently, two variants of g77 exist. One is the Free Software Foundation
|
||||
(FSF) variant. The other is the egcs variant. As of egcs version 1.1,
|
||||
these variants are kept fairly similar in most respects. Pertinent
|
||||
differences, such as the layout of the source code, are specified below.
|
||||
|
||||
Below, `[FSF]' denotes information applicable to only the FSF variant of
|
||||
g77, while `[egcs]' denotes egcs-only information.
|
||||
|
||||
|
||||
* IMPORTANT: Things you *must* do (or avoid) are marked with a * at the
|
||||
beginning of the line in this file!!!
|
||||
|
||||
|
||||
The email address to which bugs are to be reported is either
|
||||
[FSF] <fortran@gnu.org> or [egcs] <egcs-bugs@cygnus.com>.
|
||||
|
||||
* *DO NOT* send any email (reporting bugs, asking questions, etc.) to
|
||||
either of these addresses without *first* reading the g77 documentation.
|
||||
Use `info', Info mode in GNU Emacs, or a text viewer such as `more' to
|
||||
do this.
|
||||
|
||||
The g77 documentation is in the source files named `g77.info',
|
||||
`g77.info-1', `g77.info-2', and so on in the `f' subdirectory. If these
|
||||
files are not present or you can't find them, contact the person or
|
||||
organization that put together the g77 distribution you are using (probably
|
||||
not the FSF or egcs), or ask your system administrator for help.
|
||||
|
||||
|
||||
This README applies to only the g77-specific portions of the source-code
|
||||
tree that contains it. These portions include:
|
||||
|
||||
- The README.g77 and [FSF] COPYING.g77 files, in this directory, "this
|
||||
directory" being [FSF] the top-level directory containing a g77
|
||||
distribution or [egcs] the gcc/ subdirectory of an egcs distribution.
|
||||
|
||||
- The g77 front end, in the f/ subdirectory of this directory.
|
||||
|
||||
- The libg2c library, in [FSF] the f/runtime/ subdirectory of this
|
||||
directory or [egcs] the libf2c/ directory under the top-level
|
||||
directory of the egcs distribution.
|
||||
|
||||
|
||||
* To build g77, you must have a source distribution of [FSF] gcc
|
||||
version 2.8 or [egcs] egcs version 1.1. Do not attempt to use
|
||||
any other version of gcc or egcs, because this version of g77 is
|
||||
designed to work with only those versions.
|
||||
|
||||
Note that you must have *source* copies of the gcc or egcs distribution!
|
||||
You cannot build g77 just using binaries of gcc or egcs. Also, unless
|
||||
you are an expert, avoid using any distribution of gcc or egcs not
|
||||
identical to the ones distributed by the FSF and Cygnus Support,
|
||||
respectively. The primary FSF distribution site is:
|
||||
|
||||
<ftp://ftp.gnu.org/pub/gnu/>
|
||||
|
||||
The primary egcs distribution site is:
|
||||
|
||||
<ftp://ftp.cygnus.com/pub/egcs/>
|
||||
|
||||
Both of these sites have approved mirror sites from which valid
|
||||
distributions also may be obtained.
|
||||
|
||||
* Do not attempt to combine the egcs version of g77 with the FSF
|
||||
gcc distribution, or the FSF version of g77 with the egcs gcc
|
||||
distribution. Although the differences are minor, they might
|
||||
be sufficient to prevent g77 from building properly, or from
|
||||
working properly if the build appears to succeed.
|
||||
|
||||
[FSF] g77 is distributed as g77-<version>/f/ so that unpacking the g77
|
||||
distribution is done in the normal GNU way, resulting in a directory having
|
||||
the version number in the name. However, to build g77, the g77 distribution
|
||||
must be merged with an appropriate gcc distribution, normally in a gcc
|
||||
source directory, before configuring, building, and installing g77.
|
||||
|
||||
[FSF] If you have just unpacked the g77 distribution, before proceeding,
|
||||
you must merge the contents of the g77 distribution with the appropriate
|
||||
gcc distribution on your system.
|
||||
|
||||
* [FSF] Read and follow the instructions in f/INSTALL that
|
||||
explain how to merge a g77 source directory into a gcc source
|
||||
directory. You can use Info to read the same installation
|
||||
instructions via:
|
||||
|
||||
info -f f/g77.info -n Unpacking
|
||||
|
||||
[FSF] The resulting directory layout includes the following, where gcc/
|
||||
might be a link to, for example, gcc-2.8.1/:
|
||||
|
||||
gcc/ Non-g77 files in gcc
|
||||
gcc/COPYING.g77 A copy of the GPL, under which g77 is licensed
|
||||
gcc/README.g77 This file
|
||||
gcc/f/ GNU Fortran front end
|
||||
gcc/f/runtime/ libg2c configuration and g2c.h file generation
|
||||
gcc/f/runtime/libF77/ Non-I/O portion of libg2c
|
||||
gcc/f/runtime/libI77/ I/O portion of libg2c
|
||||
gcc/f/runtime/libU77/ Additional interfaces to libc for libg2c
|
||||
|
||||
[FSF] Applying g77 patches in the form of .diff files is done by typing
|
||||
`patch -p1 -d gcc' (where gcc/ contains the f/ subdirectory). That is,
|
||||
g77 patches are distributed in the same form, and at the same directory
|
||||
level, as patches to the gcc distribution. (Note: make sure you're
|
||||
using GNU patch, version 2.5 or later! Other versions of patch
|
||||
have trouble with g77-related patches.)
|
||||
|
||||
[egcs] The egcs version of g77 is distributed already merged with
|
||||
the rest of egcs (such as the gcc back end).
|
||||
|
||||
[egcs] The resulting directory layout includes the following, where egcs/
|
||||
might be a link to, for example, egcs-1.1/:
|
||||
|
||||
egcs/gcc/ Non-g77 files in gcc
|
||||
egcs/gcc/README.g77 This file
|
||||
egcs/gcc/f/ GNU Fortran front end
|
||||
egcs/libf2c/ libg2c configuration and g2c.h file generation
|
||||
egcs/libf2c/libF77/ Non-I/O portion of libg2c
|
||||
egcs/libf2c/libI77/ I/O portion of libg2c
|
||||
egcs/libf2c/libU77/ Additional interfaces to libc for libg2c
|
||||
|
||||
[egcs] Applying g77-specific patches to egcs is done the same way as
|
||||
applying other egcs patches.
|
||||
|
||||
|
||||
Below, `libf2c/' shall denote [FSF] gcc/f/runtime/ or [egcs] egcs/libf2c/,
|
||||
while `f/' shall denote [FSF] the rest of gcc/f/ or [egcs] egcs/gcc/f/.
|
||||
|
||||
|
||||
Components of note in g77 are described below.
|
||||
|
||||
f/ as a whole contains the program GNU Fortran (g77), while libf2c/
|
||||
contains a portion of the separate program f2c. Note: The libf2c
|
||||
code is not part of the program g77, just distributed with it.
|
||||
|
||||
f/ contains text files that document the Fortran compiler, source
|
||||
files for the GNU Fortran Front End (FFE), and some other stuff.
|
||||
The g77 compiler code is placed in f/ because it, along with its contents,
|
||||
is designed to be a subdirectory of a GNU CC (gcc) source directory, gcc/,
|
||||
which is structured so that language-specific front ends can be "dropped
|
||||
in" as subdirectories. The C++ front end (g++), is an example of this --
|
||||
it resides in the cp/ subdirectory. Note that the C front end (also
|
||||
referred to as gcc) is an exception to this, as its source files reside
|
||||
in the gcc/ directory itself.
|
||||
|
||||
libf2c/ contains the run-time libraries for the f2c program, also used
|
||||
by g77. These libraries normally referred to collectively as libf2c.
|
||||
When built as part of g77, libf2c is installed under the name libg2c to avoid
|
||||
conflict with any existing version of libf2c, and thus is often referred
|
||||
to as libg2c when the g77 version is specifically being referred to.
|
||||
|
||||
The netlib version of libf2c/ contains two distinct libraries, libF77 and
|
||||
libI77, each in their own subdirectories. In g77, this distinction is not
|
||||
made, beyond maintaining the subdirectory structure in the source-code tree.
|
||||
|
||||
libf2c/ is not part of the program g77, just distributed with it. It
|
||||
contains files not present in the official (netlib) version of libf2c,
|
||||
and also contains some minor changes made from libf2c, to fix some bugs,
|
||||
and to facilitate automatic configuration, building, and installation of
|
||||
libf2c (as libg2c) for use by g77 users.
|
||||
|
||||
* See libf2c/README for more information, including licensing conditions
|
||||
governing distribution of programs containing code from libg2c.
|
||||
|
||||
libg2c, g77's version of libf2c, adds Dave Love's implementation of
|
||||
libU77, in the libf2c/libU77/ directory. This library is distributed
|
||||
under the GNU Library General Public License (LGPL) -- see the
|
||||
file libf2c/libU77/COPYING.LIB for more information, as this license
|
||||
governs distribution conditions for programs containing code from
|
||||
this portion of the library.
|
||||
|
||||
|
||||
Files of note in g77 are described below.
|
||||
|
||||
f/BUGS lists some important bugs known to be in g77. Or:
|
||||
|
||||
info -f f/g77.info -n "Actual Bugs"
|
||||
|
||||
f/ChangeLog lists recent changes to g77 internals.
|
||||
|
||||
libf2c/ChangeLog lists recent changes to libg2c internals.
|
||||
|
||||
[FSF] f/INSTALL describes how to build and install GNU Fortran. Or:
|
||||
|
||||
info -f f/g77.info -n Installation
|
||||
|
||||
f/NEWS contains the per-release changes. These include the user-visible
|
||||
changes described under "Changes" in the g77 documentation, plus internal
|
||||
changes of import. Or:
|
||||
|
||||
info -f f/g77.info -n News
|
||||
|
||||
* All users of g77 (not just installers) should read f/g77.info*
|
||||
as well, using the `more' command if neither the `info' command,
|
||||
nor GNU Emacs (with its Info mode), are available, or if they
|
||||
aren't yet accustomed to using these tools. Read f/BUGS and f/NEWS
|
||||
plus, if you are planning on building or installing the FSF version
|
||||
of g77, f/INSTALL, at the very least! All of these files are
|
||||
readable as "plain text" files.
|
||||
|
||||
* Also see <ftp://alpha.gnu.org/g77.plan> for up-to-date information
|
||||
regarding g77 bug reports, known bugs, bug-fixes, and new versions.
|
||||
|
||||
|
||||
The rest of this file is of note to only those who wish to
|
||||
debug, modify, or test the FFE (in conjunction with the gcc back end).
|
||||
|
||||
If you want to explore the FFE code, which lives entirely in f/, here
|
||||
are a few clues. The file g77spec.c contains the g77-specific source code
|
||||
for the `g77' command only -- this just forms a variant of the `gcc'
|
||||
command, so, just as the `gcc' command itself does not contain
|
||||
the C front end, the `g77' command does not contain the Fortran front
|
||||
end (FFE). The FFE code ends up in an executable named `f771', which
|
||||
does the actual compiling, so it contains the FFE plus the gcc back end
|
||||
(the latter to do most of the optimization, and the code generation).
|
||||
|
||||
The file parse.c is the source file for main() for a stand-alone FFE and
|
||||
yyparse() for f771. (Stand-alone building of the FFE doesn't work these days.)
|
||||
The file top.c contains the top-level FFE function ffe_file and it (along
|
||||
with top.h) define all ffe_[a-z].*, ffe[A-Z].*, and FFE_[A-Za-z].* symbols.
|
||||
The file fini.c is a main() program that is used when building the FFE to
|
||||
generate C header and source files for recognizing keywords. The files
|
||||
malloc.c and malloc.h comprise a memory manager that defines all
|
||||
malloc_[a-z].*, malloc[A-Z].*, and MALLOC_[A-Za-z].* symbols. All other
|
||||
modules named <xyz> are comprised of all files named <xyz>*.<ext> and
|
||||
define all ffe<xyz>_[a-z].*, ffe<xyz>[A-Z].*, and FFE<XYZ>_[A-Za-z].* symbols.
|
||||
If you understand all this, congratulations -- it's easier for me to remember
|
||||
how it works than to type in these grep patterns (such as they are). But it
|
||||
does make it easy to find where a symbol is defined -- for example,
|
||||
the symbol "ffexyz_set_something" would be defined in xyz.h and implemented
|
||||
there (if it's a macro) or in xyz.c.
|
||||
|
||||
The "porting" files of note currently are: proj.h, which defines the
|
||||
"language" used by all the other source files (the language being
|
||||
Standard C plus some useful things like ARRAY_SIZE and such) -- change
|
||||
this file when you find your system doesn't properly define a Standard C
|
||||
macro or function, for example; target.h and target.c, which describe
|
||||
the target machine in terms of what data types are supported, how they are
|
||||
denoted (what C type does an INTEGER*8 map to, for example), how to convert
|
||||
between them, and so on (though as of 0.5.3, more and more of this information
|
||||
is being dynamically configured by ffecom_init_0); com.h and com.c, which
|
||||
interface to the target back end (currently only FFE stand-alone and the GBE);
|
||||
ste.c, which contains code for implementing recognized executable statements
|
||||
in the target back end (again currently either FFE or GBE); src.h and src.c,
|
||||
which describe information on the format(s) of source files (such as whether
|
||||
they are never to be processed as case-insensitive with regard to Fortran
|
||||
keywords); and proj.c, which contains whatever code is needed to support
|
||||
the language defined by proj.h.
|
||||
|
||||
If you want to debug the f771 executable, for example if it crashes,
|
||||
note that the global variables "lineno" and "input_filename" are set
|
||||
to reflect the current line being read by the lexer during the first-pass
|
||||
analysis of a program unit and to reflect the current line being
|
||||
processed during the second-pass compilation of a program unit. If
|
||||
an invocation of the function ffestd_exec_end() is on the stack,
|
||||
the compiler is in the second pass, otherwise it is in the first.
|
||||
(This information might help you reduce a test case and/or work around
|
||||
a bug in g77 until a fix is available.)
|
||||
|
||||
Any questions or comments on these topics? Read the g77 documentation!
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
/* alloca.c -- allocate automatically reclaimed memory
|
||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||
|
||||
This implementation of the PWB library alloca function,
|
||||
which is used to allocate space off the run-time stack so
|
||||
that it is automatically reclaimed upon procedure exit,
|
||||
was inspired by discussions with J. Q. Johnson of Cornell.
|
||||
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||
|
||||
There are some preprocessor constants that can
|
||||
be defined when compiling for your specific system, for
|
||||
improved efficiency; however, the defaults should be okay.
|
||||
|
||||
The general concept of this implementation is to keep
|
||||
track of all alloca-allocated blocks, and reclaim any
|
||||
that are found to be deeper in the stack than the current
|
||||
invocation. This heuristic does not reclaim storage as
|
||||
soon as it becomes invalid, but it will do so eventually.
|
||||
|
||||
As a special case, alloca(0) reclaims storage without
|
||||
allocating any. It is a good idea to use alloca(0) in
|
||||
your main control loop, etc. to force garbage collection. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef emacs
|
||||
#include "blockinput.h"
|
||||
#endif
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
#if !defined (__GNUC__) || __GNUC__ < 2
|
||||
|
||||
/* If someone has defined alloca as a macro,
|
||||
there must be some other way alloca is supposed to work. */
|
||||
#ifndef alloca
|
||||
|
||||
#ifdef emacs
|
||||
#ifdef static
|
||||
/* actually, only want this if static is defined as ""
|
||||
-- this is for usg, in which emacs must undefine static
|
||||
in order to make unexec workable
|
||||
*/
|
||||
#ifndef STACK_DIRECTION
|
||||
you
|
||||
lose
|
||||
-- must know STACK_DIRECTION at compile-time
|
||||
#endif /* STACK_DIRECTION undefined */
|
||||
#endif /* static */
|
||||
#endif /* emacs */
|
||||
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc ();
|
||||
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
#else
|
||||
#define ADDRESS_FUNCTION(arg) &(arg)
|
||||
#endif
|
||||
|
||||
#if __STDC__
|
||||
typedef void *pointer;
|
||||
#else
|
||||
typedef char *pointer;
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/* Different portions of Emacs need to call different versions of
|
||||
malloc. The Emacs executable needs alloca to call xmalloc, because
|
||||
ordinary malloc isn't protected from input signals. On the other
|
||||
hand, the utilities in lib-src need alloca to call malloc; some of
|
||||
them are very simple, and don't have an xmalloc routine.
|
||||
|
||||
Non-Emacs programs expect this to call use xmalloc.
|
||||
|
||||
Callers below should use malloc. */
|
||||
|
||||
#ifndef emacs
|
||||
#define malloc xmalloc
|
||||
#endif
|
||||
extern pointer malloc ();
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
#define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
#endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
|
||||
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
#define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction ()
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
|
||||
if (addr == NULL)
|
||||
{ /* Initial entry. */
|
||||
addr = ADDRESS_FUNCTION (dummy);
|
||||
|
||||
find_stack_direction (); /* Recurse once. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second entry. */
|
||||
if (ADDRESS_FUNCTION (dummy) > addr)
|
||||
stack_dir = 1; /* Stack grew upward. */
|
||||
else
|
||||
stack_dir = -1; /* Stack grew downward. */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
(b) keep track of stack depth.
|
||||
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
#ifndef ALIGN_SIZE
|
||||
#define ALIGN_SIZE sizeof(double)
|
||||
#endif
|
||||
|
||||
typedef union hdr
|
||||
{
|
||||
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||
struct
|
||||
{
|
||||
union hdr *next; /* For chaining headers. */
|
||||
char *deep; /* For stack depth measure. */
|
||||
} h;
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
|
||||
/* Return a pointer to at least SIZE bytes of storage,
|
||||
which will be automatically reclaimed upon exit from
|
||||
the procedure that called alloca. Originally, this space
|
||||
was supposed to be taken from the current stack frame of the
|
||||
caller, but that method cannot be made to work for some
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca (size)
|
||||
unsigned size;
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION (probe);
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction ();
|
||||
#endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that
|
||||
was allocated from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
register header *hp; /* Traverses linked list. */
|
||||
|
||||
#ifdef emacs
|
||||
BLOCK_INPUT;
|
||||
#endif
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||
|| (STACK_DIR < 0 && hp->h.deep < depth))
|
||||
{
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free ((pointer) hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
}
|
||||
else
|
||||
break; /* Rest are not deeper. */
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage. */
|
||||
|
||||
#ifdef emacs
|
||||
UNBLOCK_INPUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return NULL; /* No allocation required. */
|
||||
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
register pointer new = malloc (sizeof (header) + size);
|
||||
/* Address of header. */
|
||||
|
||||
if (new == 0)
|
||||
abort();
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (pointer) ((char *) new + sizeof (header));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef CRAY_STACK
|
||||
#define CRAY_STACK
|
||||
#ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header
|
||||
{
|
||||
long shgrow:32; /* Number of times stack has grown. */
|
||||
long shaseg:32; /* Size of increments to stack. */
|
||||
long shhwm:32; /* High water mark of stack. */
|
||||
long shsize:32; /* Current size of stack (all segments). */
|
||||
};
|
||||
|
||||
/* The stack segment linkage control information occurs at
|
||||
the high-address end of a stack segment. (The stack
|
||||
grows from low addresses to high addresses.) The initial
|
||||
part of the stack segment linkage control information is
|
||||
0200 (octal) words. This provides for register storage
|
||||
for the routine which overflows the stack. */
|
||||
|
||||
struct stack_segment_linkage
|
||||
{
|
||||
long ss[0200]; /* 0200 overflow words. */
|
||||
long sssize:32; /* Number of words in this segment. */
|
||||
long ssbase:32; /* Offset to stack base. */
|
||||
long:32;
|
||||
long sspseg:32; /* Offset to linkage control of previous
|
||||
segment of stack. */
|
||||
long:32;
|
||||
long sstcpt:32; /* Pointer to task common address block. */
|
||||
long sscsnm; /* Private control structure number for
|
||||
microtasking. */
|
||||
long ssusr1; /* Reserved for user. */
|
||||
long ssusr2; /* Reserved for user. */
|
||||
long sstpid; /* Process ID for pid based multi-tasking. */
|
||||
long ssgvup; /* Pointer to multitasking thread giveup. */
|
||||
long sscray[7]; /* Reserved for Cray Research. */
|
||||
long ssa0;
|
||||
long ssa1;
|
||||
long ssa2;
|
||||
long ssa3;
|
||||
long ssa4;
|
||||
long ssa5;
|
||||
long ssa6;
|
||||
long ssa7;
|
||||
long sss0;
|
||||
long sss1;
|
||||
long sss2;
|
||||
long sss3;
|
||||
long sss4;
|
||||
long sss5;
|
||||
long sss6;
|
||||
long sss7;
|
||||
};
|
||||
|
||||
#else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat
|
||||
{
|
||||
long now; /* Current total stack size. */
|
||||
long maxc; /* Amount of contiguous space which would
|
||||
be required to satisfy the maximum
|
||||
stack demand to date. */
|
||||
long high_water; /* Stack high-water mark. */
|
||||
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
|
||||
long hits; /* Number of internal buffer hits. */
|
||||
long extends; /* Number of block extensions. */
|
||||
long stko_mallocs; /* Block allocations by $STKOFEN. */
|
||||
long underflows; /* Number of stack underflow calls ($STKRETN). */
|
||||
long stko_free; /* Number of deallocations by $STKRETN. */
|
||||
long stkm_free; /* Number of deallocations by $STKMRET. */
|
||||
long segments; /* Current number of stack segments. */
|
||||
long maxs; /* Maximum number of stack segments so far. */
|
||||
long pad_size; /* Stack pad size. */
|
||||
long current_address; /* Current stack segment address. */
|
||||
long current_size; /* Current stack segment size. This
|
||||
number is actually corrupted by STKSTAT to
|
||||
include the fifteen word trailer area. */
|
||||
long initial_address; /* Address of initial segment. */
|
||||
long initial_size; /* Size of initial segment. */
|
||||
};
|
||||
|
||||
/* The following structure describes the data structure which trails
|
||||
any stack segment. I think that the description in 'asdef' is
|
||||
out of date. I only describe the parts that I am sure about. */
|
||||
|
||||
struct stk_trailer
|
||||
{
|
||||
long this_address; /* Address of this block. */
|
||||
long this_size; /* Size of this block (does not include
|
||||
this trailer). */
|
||||
long unknown2;
|
||||
long unknown3;
|
||||
long link; /* Address of trailer block of previous
|
||||
segment. */
|
||||
long unknown5;
|
||||
long unknown6;
|
||||
long unknown7;
|
||||
long unknown8;
|
||||
long unknown9;
|
||||
long unknown10;
|
||||
long unknown11;
|
||||
long unknown12;
|
||||
long unknown13;
|
||||
long unknown14;
|
||||
};
|
||||
|
||||
#endif /* CRAY2 */
|
||||
#endif /* not CRAY_STACK */
|
||||
|
||||
#ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc (long *address)
|
||||
{
|
||||
struct stk_stat status;
|
||||
struct stk_trailer *trailer;
|
||||
long *block, size;
|
||||
long result = 0;
|
||||
|
||||
/* We want to iterate through all of the segments. The first
|
||||
step is to get the stack status structure. We could do this
|
||||
more quickly and more directly, perhaps, by referencing the
|
||||
$LM00 common block, but I know that this works. */
|
||||
|
||||
STKSTAT (&status);
|
||||
|
||||
/* Set up the iteration. */
|
||||
|
||||
trailer = (struct stk_trailer *) (status.current_address
|
||||
+ status.current_size
|
||||
- 15);
|
||||
|
||||
/* There must be at least one stack segment. Therefore it is
|
||||
a fatal error if "trailer" is null. */
|
||||
|
||||
if (trailer == 0)
|
||||
abort ();
|
||||
|
||||
/* Discard segments that do not contain our argument address. */
|
||||
|
||||
while (trailer != 0)
|
||||
{
|
||||
block = (long *) trailer->this_address;
|
||||
size = trailer->this_size;
|
||||
if (block == 0 || size == 0)
|
||||
abort ();
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
if ((block <= address) && (address < (block + size)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the result to the offset in this segment and add the sizes
|
||||
of all predecessor segments. */
|
||||
|
||||
result = address - block;
|
||||
|
||||
if (trailer == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (trailer->this_size <= 0)
|
||||
abort ();
|
||||
result += trailer->this_size;
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
}
|
||||
while (trailer != 0);
|
||||
|
||||
/* We are done. Note that if you present a bogus address (one
|
||||
not in any segment), you will get a different number back, formed
|
||||
from subtracting the address of the first block. This is probably
|
||||
not what you want. */
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
#else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
routine is to linearize, in some sense, stack addresses
|
||||
for alloca. */
|
||||
|
||||
static long
|
||||
i00afunc (long address)
|
||||
{
|
||||
long stkl = 0;
|
||||
|
||||
long size, pseg, this_segment, stack;
|
||||
long result = 0;
|
||||
|
||||
struct stack_segment_linkage *ssptr;
|
||||
|
||||
/* Register B67 contains the address of the end of the
|
||||
current stack segment. If you (as a subprogram) store
|
||||
your registers on the stack and find that you are past
|
||||
the contents of B67, you have overflowed the segment.
|
||||
|
||||
B67 also points to the stack segment linkage control
|
||||
area, which is what we are really interested in. */
|
||||
|
||||
stkl = CRAY_STACKSEG_END ();
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
|
||||
/* If one subtracts 'size' from the end of the segment,
|
||||
one has the address of the first word of the segment.
|
||||
|
||||
If this is not the first segment, 'pseg' will be
|
||||
nonzero. */
|
||||
|
||||
pseg = ssptr->sspseg;
|
||||
size = ssptr->sssize;
|
||||
|
||||
this_segment = stkl - size;
|
||||
|
||||
/* It is possible that calling this routine itself caused
|
||||
a stack overflow. Discard stack segments which do not
|
||||
contain the target address. */
|
||||
|
||||
while (!(this_segment <= address && address <= stkl))
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
|
||||
#endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
this_segment = stkl - size;
|
||||
}
|
||||
|
||||
result = address - this_segment;
|
||||
|
||||
/* If you subtract pseg from the current end of the stack,
|
||||
you get the address of the previous stack segment's end.
|
||||
This seems a little convoluted to me, but I'll bet you save
|
||||
a cycle somewhere. */
|
||||
|
||||
while (pseg != 0)
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o\n", pseg, size);
|
||||
#endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
result += size;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#endif /* not CRAY2 */
|
||||
#endif /* CRAY */
|
||||
|
||||
#endif /* no alloca */
|
||||
#endif /* not GCC version 2 */
|
||||
|
|
@ -1,992 +0,0 @@
|
|||
/* Output bytecodes for GNU C-compiler.
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include "machmode.h"
|
||||
#include "rtl.h"
|
||||
#include "real.h"
|
||||
#include "obstack.h"
|
||||
#include "bytecode.h"
|
||||
#ifdef __GNUC__
|
||||
#include "bytetypes.h"
|
||||
#endif
|
||||
#include "bc-emit.h"
|
||||
#include "bc-opcode.h"
|
||||
#include "bc-typecd.h"
|
||||
#include "bi-run.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern char *xmalloc (), *xrealloc ();
|
||||
extern void free ();
|
||||
|
||||
extern struct obstack *rtl_obstack;
|
||||
|
||||
/* Indexed by mode class, gives the narrowest mode for each class. */
|
||||
|
||||
extern enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
|
||||
|
||||
/* Commonly used modes. */
|
||||
/* Mode whose width is BITS_PER_UNIT */
|
||||
extern enum machine_mode byte_mode;
|
||||
|
||||
/* Mode whose width is BITS_PER_WORD */
|
||||
extern enum machine_mode word_mode;
|
||||
|
||||
/* Vector indexed by opcode giving info about the args for each opcode. */
|
||||
static struct arityvec arityvec[] = {
|
||||
#include "bc-arity.h"
|
||||
};
|
||||
|
||||
/* How to print a symbol name for the assembler. */
|
||||
static void
|
||||
prsym (file, s)
|
||||
FILE *file;
|
||||
char *s;
|
||||
{
|
||||
if (*s == '*')
|
||||
fprintf (file, "%s", s + 1);
|
||||
else
|
||||
|
||||
#ifdef NAMES_HAVE_UNDERSCORES
|
||||
fprintf (file, "_%s", s);
|
||||
#else
|
||||
fprintf (file, "%s", s);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Maintain a bucket hash table for symbol names. */
|
||||
|
||||
#define HASH_BITS 32
|
||||
#define HASH_SIZE 509
|
||||
|
||||
static struct bc_sym *hashtab[HASH_SIZE];
|
||||
|
||||
static unsigned int
|
||||
hash (name)
|
||||
char *name;
|
||||
{
|
||||
unsigned int hash = 0;
|
||||
|
||||
while (*name)
|
||||
{
|
||||
hash = hash << 3 | hash >> HASH_BITS - 3;
|
||||
hash += *name++;
|
||||
}
|
||||
|
||||
return hash % HASH_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/* Look up the named symbol, creating it if it doesn't exist. */
|
||||
struct bc_sym *
|
||||
sym_lookup (name)
|
||||
char *name;
|
||||
{
|
||||
int i;
|
||||
struct bc_sym *s;
|
||||
|
||||
i = hash (name);
|
||||
for (s = hashtab[i]; s; s = s->next)
|
||||
if (!strcmp (s->name, name))
|
||||
return s;
|
||||
|
||||
s = (struct bc_sym *) xmalloc (sizeof (struct bc_sym));
|
||||
s->name = xmalloc (strlen (name) + 1);
|
||||
strcpy (s->name, name);
|
||||
s->defined = s->global = s->common = 0;
|
||||
s->val = 0;
|
||||
s->next = hashtab[i];
|
||||
hashtab[i] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/* Write out .globl and common symbols to the named file. */
|
||||
static void
|
||||
bc_sym_write (file)
|
||||
FILE *file;
|
||||
{
|
||||
int i;
|
||||
struct bc_sym *s;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; ++i)
|
||||
for (s = hashtab[i]; s; s = s->next)
|
||||
{
|
||||
if (s->global)
|
||||
{
|
||||
fprintf (file, "\n\t.globl ");
|
||||
prsym (file, s->name);
|
||||
putc ('\n', file);
|
||||
if (s->common)
|
||||
{
|
||||
fprintf (file, "\n\t.comm ");
|
||||
prsym (file, s->name);
|
||||
fprintf (file, ", %lu\n", s->val);
|
||||
}
|
||||
}
|
||||
else if (s->common)
|
||||
{
|
||||
fprintf (file, "\n\t.lcomm ");
|
||||
prsym (file, s->name);
|
||||
fprintf (file, ", %lu\n", s->val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create and initialize a new segment. */
|
||||
static struct bc_seg *
|
||||
seg_create ()
|
||||
{
|
||||
struct bc_seg *result;
|
||||
|
||||
result = (struct bc_seg *) xmalloc (sizeof (struct bc_seg));
|
||||
result->alloc = 256;
|
||||
result->data = xmalloc (result->alloc);
|
||||
result->size = 0;
|
||||
result->syms = 0;
|
||||
result->relocs = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Advance the segment index to the next alignment boundary. */
|
||||
static void
|
||||
seg_align (seg, log)
|
||||
struct bc_seg *seg;
|
||||
int log;
|
||||
{
|
||||
unsigned int oldsize = seg->size;
|
||||
|
||||
seg->size = seg->size + (1 << log) - 1 & ~((1 << log) - 1);
|
||||
if (seg->size > seg->alloc)
|
||||
{
|
||||
while (seg->size > seg->alloc)
|
||||
seg->alloc *= 2;
|
||||
seg->data = xrealloc (seg->data, seg->alloc);
|
||||
}
|
||||
bzero (seg->data + oldsize, seg->size - oldsize);
|
||||
}
|
||||
|
||||
|
||||
/* Append the given data to the given segment. */
|
||||
static void
|
||||
seg_data (seg, data, size)
|
||||
struct bc_seg *seg;
|
||||
char *data;
|
||||
unsigned int size;
|
||||
{
|
||||
if (seg->size + size > seg->alloc)
|
||||
{
|
||||
while (seg->size + size > seg->alloc)
|
||||
seg->alloc *= 2;
|
||||
seg->data = xrealloc (seg->data, seg->alloc);
|
||||
}
|
||||
|
||||
bcopy (data, seg->data + seg->size, size);
|
||||
seg->size += size;
|
||||
}
|
||||
|
||||
|
||||
/* Append a zero-filled skip to the given segment. */
|
||||
static void
|
||||
seg_skip (seg, size)
|
||||
struct bc_seg *seg;
|
||||
unsigned int size;
|
||||
{
|
||||
if (seg->size + size > seg->alloc)
|
||||
{
|
||||
while (seg->size + size > seg->alloc)
|
||||
seg->alloc *= 2;
|
||||
seg->data = xrealloc (seg->data, seg->alloc);
|
||||
}
|
||||
|
||||
memset (seg->data + seg->size, 0, size);
|
||||
seg->size += size;
|
||||
}
|
||||
|
||||
|
||||
/* Define the given name as the current offset in the given segment. It
|
||||
is an error if the name is already defined. Return 0 or 1 indicating
|
||||
failure or success respectively. */
|
||||
static int
|
||||
seg_defsym (seg, name)
|
||||
struct bc_seg *seg;
|
||||
char *name;
|
||||
{
|
||||
struct bc_sym *sym;
|
||||
struct bc_segsym *segsym;
|
||||
|
||||
sym = sym_lookup (name);
|
||||
if (sym->defined)
|
||||
return 0;
|
||||
|
||||
sym->defined = 1;
|
||||
sym->val = seg->size;
|
||||
segsym = (struct bc_segsym *) xmalloc (sizeof (struct bc_segsym));
|
||||
segsym->sym = sym;
|
||||
segsym->next = seg->syms;
|
||||
seg->syms = segsym;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Generate in seg's data a reference to the given sym, adjusted by
|
||||
the given offset. */
|
||||
static void
|
||||
seg_refsym (seg, name, offset)
|
||||
struct bc_seg *seg;
|
||||
char *name;
|
||||
int offset;
|
||||
{
|
||||
struct bc_sym *sym;
|
||||
struct bc_segreloc *segreloc;
|
||||
|
||||
sym = sym_lookup (name);
|
||||
segreloc = (struct bc_segreloc *) xmalloc (sizeof (struct bc_segreloc));
|
||||
segreloc->offset = seg->size;
|
||||
segreloc->sym = sym;
|
||||
segreloc->next = seg->relocs;
|
||||
seg->relocs = segreloc;
|
||||
seg_data (seg, (char *) &offset, sizeof offset);
|
||||
}
|
||||
|
||||
|
||||
/* Concatenate the contents of given segments into the first argument. */
|
||||
static void
|
||||
seg_concat (result, seg)
|
||||
struct bc_seg *result, *seg;
|
||||
{
|
||||
unsigned int fix;
|
||||
struct bc_segsym *segsym;
|
||||
struct bc_segreloc *segreloc;
|
||||
|
||||
seg_align (result, MACHINE_SEG_ALIGN);
|
||||
fix = result->size;
|
||||
seg_data (result, seg->data, seg->size);
|
||||
free (seg->data);
|
||||
|
||||
/* Go through the symbols and relocs of SEG, adjusting their offsets
|
||||
for their new location in RESULT. */
|
||||
if (seg->syms)
|
||||
{
|
||||
segsym = seg->syms;
|
||||
do
|
||||
segsym->sym->val += fix;
|
||||
while (segsym->next && (segsym = segsym->next));
|
||||
segsym->next = result->syms;
|
||||
result->syms = seg->syms;
|
||||
}
|
||||
if (seg->relocs)
|
||||
{
|
||||
segreloc = seg->relocs;
|
||||
do
|
||||
segreloc->offset += fix;
|
||||
while (segreloc->next && (segreloc = segreloc->next));
|
||||
segreloc->next = result->relocs;
|
||||
result->relocs = seg->relocs;
|
||||
}
|
||||
|
||||
free ((char *) seg);
|
||||
}
|
||||
|
||||
/* Write a segment to a file. */
|
||||
static void
|
||||
bc_seg_write (seg, file)
|
||||
struct bc_seg *seg;
|
||||
FILE *file;
|
||||
{
|
||||
struct bc_segsym *segsym, *nsegsym, *psegsym;
|
||||
struct bc_segreloc *segreloc, *nsegreloc, *psegreloc;
|
||||
int i, offset, flag;
|
||||
|
||||
/* Reverse the list of symbols. */
|
||||
for (psegsym = 0, segsym = seg->syms; segsym; segsym = nsegsym)
|
||||
{
|
||||
nsegsym = segsym->next;
|
||||
segsym->next = psegsym;
|
||||
psegsym = segsym;
|
||||
}
|
||||
seg->syms = psegsym;
|
||||
|
||||
/* Reverse the list of relocs. */
|
||||
for (psegreloc = 0, segreloc = seg->relocs; segreloc; segreloc = nsegreloc)
|
||||
{
|
||||
nsegreloc = segreloc->next;
|
||||
segreloc->next = psegreloc;
|
||||
psegreloc = segreloc;
|
||||
}
|
||||
seg->relocs = psegreloc;
|
||||
|
||||
/* Output each byte of the segment. */
|
||||
for (i = 0, segsym = seg->syms, segreloc = seg->relocs; i < seg->size; ++i)
|
||||
{
|
||||
while (segsym && segsym->sym->val == i)
|
||||
{
|
||||
if (i % 8 != 0)
|
||||
putc ('\n', file);
|
||||
|
||||
BC_WRITE_SEGSYM (segsym, file);
|
||||
segsym = segsym->next;
|
||||
flag = 1;
|
||||
}
|
||||
if (segreloc && segreloc->offset == i)
|
||||
{
|
||||
if (i % 8 != 0)
|
||||
putc ('\n', file);
|
||||
|
||||
bcopy (seg->data + i, (char *) &offset, sizeof (int));
|
||||
i += sizeof (int) - 1;
|
||||
|
||||
BC_WRITE_RELOC_ENTRY (segreloc, file, offset);
|
||||
segreloc = segreloc->next;
|
||||
flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i % 8 == 0 || flag)
|
||||
BC_START_BYTECODE_LINE (file);
|
||||
|
||||
BC_WRITE_BYTECODE (i % 8 == 0 || flag ? ' ' : ',',
|
||||
seg->data[i] & 0xFF,
|
||||
file);
|
||||
flag = 0;
|
||||
if (i % 8 == 7)
|
||||
putc ('\n', file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Paranoia check--we should have visited all syms and relocs during
|
||||
the output pass. */
|
||||
|
||||
if (segsym || segreloc)
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Text and data segments of the object file in making. */
|
||||
static struct bc_seg *bc_text_seg;
|
||||
static struct bc_seg *bc_data_seg;
|
||||
|
||||
/* Called before anything else in this module. */
|
||||
void
|
||||
bc_initialize ()
|
||||
{
|
||||
int min_class_size[(int) MAX_MODE_CLASS];
|
||||
enum machine_mode mode;
|
||||
int i;
|
||||
|
||||
bc_init_mode_to_code_map ();
|
||||
|
||||
bc_text_seg = seg_create ();
|
||||
bc_data_seg = seg_create ();
|
||||
|
||||
dconst0 = REAL_VALUE_ATOF ("0", DFmode);
|
||||
dconst1 = REAL_VALUE_ATOF ("1", DFmode);
|
||||
dconst2 = REAL_VALUE_ATOF ("2", DFmode);
|
||||
dconstm1 = REAL_VALUE_ATOF ("-1", DFmode);
|
||||
|
||||
/* Find the narrowest mode for each class and compute the word and byte
|
||||
modes. */
|
||||
|
||||
for (i = 0; i < (int) MAX_MODE_CLASS; i++)
|
||||
min_class_size[i] = 1000;
|
||||
|
||||
for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
|
||||
mode = (enum machine_mode) ((int) mode + 1))
|
||||
{
|
||||
if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
|
||||
{
|
||||
class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
|
||||
min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
|
||||
}
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_BITSIZE (mode) == BITS_PER_UNIT)
|
||||
byte_mode = mode;
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
|
||||
word_mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* External addresses referenced in a function. Rather than trying to
|
||||
work relocatable address directly into bytecoded functions (which would
|
||||
require us to provide hairy location info and possibly obey alignment
|
||||
rules imposed by the architecture) we build an auxiliary table of
|
||||
pointer constants, and encode just offsets into this table into the
|
||||
actual bytecode. */
|
||||
static struct bc_seg *ptrconsts;
|
||||
|
||||
/* Trampoline code for the function entry. */
|
||||
struct bc_seg *trampoline;
|
||||
|
||||
/* Actual byte code of the function. */
|
||||
struct bc_seg *bytecode;
|
||||
|
||||
/* List of labels defined in the function. */
|
||||
struct bc_label *labels;
|
||||
|
||||
/* List of label references in the function. */
|
||||
struct bc_labelref *labelrefs;
|
||||
|
||||
|
||||
/* Add symbol to pointer table. Return offset into table where
|
||||
pointer was stored. The offset usually goes into the bytecode
|
||||
stream as a constP literal. */
|
||||
int
|
||||
bc_define_pointer (p)
|
||||
char *p;
|
||||
{
|
||||
int offset = ptrconsts->size;
|
||||
|
||||
seg_refsym (ptrconsts, p, 0);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
/* Begin a bytecoded function. */
|
||||
int
|
||||
bc_begin_function (name)
|
||||
char *name;
|
||||
{
|
||||
ptrconsts = seg_create ();
|
||||
trampoline = seg_create ();
|
||||
bytecode = seg_create ();
|
||||
return seg_defsym (trampoline, name);
|
||||
}
|
||||
|
||||
|
||||
/* Force alignment in inline bytecode. */
|
||||
void
|
||||
bc_align_bytecode (align)
|
||||
int align;
|
||||
{
|
||||
seg_align (bytecode, align);
|
||||
}
|
||||
|
||||
|
||||
/* Emit data inline into bytecode. */
|
||||
void
|
||||
bc_emit_bytecode_const (data, size)
|
||||
char *data;
|
||||
unsigned int size;
|
||||
{
|
||||
if (bytecode)
|
||||
seg_data (bytecode, data, size);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new "bytecode label", to have its value defined later.
|
||||
Bytecode labels have nothing to do with the object file symbol table,
|
||||
and are purely local to a given bytecoded function. */
|
||||
struct bc_label *
|
||||
bc_get_bytecode_label ()
|
||||
{
|
||||
struct bc_label *result;
|
||||
|
||||
result = (struct bc_label *) xmalloc (sizeof (struct bc_label));
|
||||
result->defined = 0;
|
||||
result->next = labels;
|
||||
result->uid = 0;
|
||||
labels = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Define the given label with the current location counter. */
|
||||
int
|
||||
bc_emit_bytecode_labeldef (label)
|
||||
struct bc_label *label;
|
||||
{
|
||||
extern int bc_new_uid ();
|
||||
|
||||
if (!label || label->defined)
|
||||
return 0;
|
||||
|
||||
label->offset = bytecode->size;
|
||||
label->defined = 1;
|
||||
label->uid = bc_new_uid ();
|
||||
|
||||
#ifdef DEBUG_PRINT_CODE
|
||||
fprintf (stderr, "$%lx:\n", label);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Generate a location-relative reference to the given bytecode label.
|
||||
It need not be defined yet; label references will be backpatched later. */
|
||||
void
|
||||
bc_emit_bytecode_labelref (label)
|
||||
struct bc_label *label;
|
||||
{
|
||||
struct bc_labelref *labelref;
|
||||
static int zero;
|
||||
|
||||
labelref = (struct bc_labelref *) xmalloc (sizeof (struct bc_labelref));
|
||||
labelref->label = label;
|
||||
labelref->offset = bytecode->size;
|
||||
labelref->next = labelrefs;
|
||||
labelrefs = labelref;
|
||||
|
||||
#ifdef DEBUG_PRINT_CODE
|
||||
fprintf (stderr, " $%lx", label);
|
||||
#endif
|
||||
|
||||
seg_data (bytecode, (char *) &zero, sizeof zero);
|
||||
}
|
||||
|
||||
|
||||
/* Emit a reference to an external address; generate the reference in the
|
||||
ptrconst area, and emit an offset in the bytecode. */
|
||||
void
|
||||
bc_emit_code_labelref (name, offset)
|
||||
char *name;
|
||||
int offset;
|
||||
{
|
||||
int ptroff;
|
||||
|
||||
ptroff = ptrconsts->size / sizeof (char *);
|
||||
seg_data (bytecode, (char *) &ptroff, sizeof ptroff);
|
||||
seg_refsym (ptrconsts, name, offset);
|
||||
|
||||
#ifdef DEBUG_PRINT_CODE
|
||||
fprintf (stderr, " [external <%x> %s]", ptroff, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Backpatch label references in the byte code, and concatenate the bytecode
|
||||
and pointer constant segments to the cumulative text for the object file.
|
||||
Return a label name for the pointer constants region. */
|
||||
char *
|
||||
bc_end_function ()
|
||||
{
|
||||
int addr;
|
||||
struct bc_label *label, *next;
|
||||
struct bc_labelref *ref, *nextref;
|
||||
char ptrconsts_label[20];
|
||||
static int nlab;
|
||||
|
||||
/* Backpatch bytecode label references. */
|
||||
for (ref = labelrefs; ref; ref = ref->next)
|
||||
if (ref->label->defined)
|
||||
{
|
||||
addr = ref->label->offset;
|
||||
bcopy ((char *) &addr, bytecode->data + ref->offset, sizeof addr);
|
||||
}
|
||||
|
||||
/* Free the chains of labelrefs and labeldefs. */
|
||||
for (ref = labelrefs; ref; ref = nextref)
|
||||
{
|
||||
nextref = ref->next;
|
||||
free ((char *) ref);
|
||||
}
|
||||
|
||||
for (label = labels; label; label = next)
|
||||
{
|
||||
next = label->next;
|
||||
free ((char *) label);
|
||||
}
|
||||
|
||||
seg_concat (trampoline, bytecode);
|
||||
seg_align (trampoline, MACHINE_SEG_ALIGN);
|
||||
sprintf (ptrconsts_label, "*LP%d", nlab++);
|
||||
seg_defsym (trampoline, ptrconsts_label);
|
||||
seg_concat (trampoline, ptrconsts);
|
||||
seg_concat (bc_text_seg, trampoline);
|
||||
|
||||
labels = 0;
|
||||
labelrefs = 0;
|
||||
trampoline = 0;
|
||||
bytecode = 0;
|
||||
ptrconsts = 0;
|
||||
|
||||
return sym_lookup (ptrconsts_label)->name;
|
||||
}
|
||||
|
||||
/* Force alignment in const data. */
|
||||
void
|
||||
bc_align_const (align)
|
||||
int align;
|
||||
{
|
||||
seg_align (bc_text_seg, align);
|
||||
}
|
||||
|
||||
/* Emit const data. */
|
||||
void
|
||||
bc_emit_const (data, size)
|
||||
char *data;
|
||||
unsigned int size;
|
||||
{
|
||||
seg_data (bc_text_seg, data, size);
|
||||
}
|
||||
|
||||
/* Emit a zero-filled constant skip. */
|
||||
void
|
||||
bc_emit_const_skip (size)
|
||||
unsigned int size;
|
||||
{
|
||||
seg_skip (bc_text_seg, size);
|
||||
}
|
||||
|
||||
/* Emit a label definition in const data. */
|
||||
int
|
||||
bc_emit_const_labeldef (name)
|
||||
char *name;
|
||||
{
|
||||
return seg_defsym (bc_text_seg, name);
|
||||
}
|
||||
|
||||
/* Emit a label reference in const data. */
|
||||
void
|
||||
bc_emit_const_labelref (name, offset)
|
||||
char *name;
|
||||
int offset;
|
||||
{
|
||||
seg_refsym (bc_text_seg, name, offset);
|
||||
}
|
||||
|
||||
/* Force alignment in data. */
|
||||
void
|
||||
bc_align_data (align)
|
||||
int align;
|
||||
{
|
||||
seg_align (bc_data_seg, align);
|
||||
}
|
||||
|
||||
/* Emit data. */
|
||||
void
|
||||
bc_emit_data (data, size)
|
||||
char *data;
|
||||
unsigned int size;
|
||||
{
|
||||
seg_data (bc_data_seg, data, size);
|
||||
}
|
||||
|
||||
/* Emit a zero-filled data skip. */
|
||||
void
|
||||
bc_emit_data_skip (size)
|
||||
unsigned int size;
|
||||
{
|
||||
seg_skip (bc_data_seg, size);
|
||||
}
|
||||
|
||||
/* Emit label definition in data. */
|
||||
int
|
||||
bc_emit_data_labeldef (name)
|
||||
char *name;
|
||||
{
|
||||
return seg_defsym (bc_data_seg, name);
|
||||
}
|
||||
|
||||
/* Emit label reference in data. */
|
||||
void
|
||||
bc_emit_data_labelref (name, offset)
|
||||
char *name;
|
||||
int offset;
|
||||
{
|
||||
seg_refsym (bc_data_seg, name, offset);
|
||||
}
|
||||
|
||||
/* Emit a common block of the given name and size. Note that
|
||||
when the .o file is actually written non-global "common"
|
||||
blocks will have to be turned into space in the data section. */
|
||||
int
|
||||
bc_emit_common (name, size)
|
||||
char *name;
|
||||
unsigned int size;
|
||||
{
|
||||
struct bc_sym *sym;
|
||||
|
||||
sym = sym_lookup (name);
|
||||
if (sym->defined)
|
||||
return 0;
|
||||
|
||||
sym->defined = 1;
|
||||
sym->common = 1;
|
||||
sym->val = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Globalize the given label. */
|
||||
void
|
||||
bc_globalize_label (name)
|
||||
char *name;
|
||||
{
|
||||
struct bc_sym *sym;
|
||||
|
||||
sym = sym_lookup (name);
|
||||
sym->global = 1;
|
||||
}
|
||||
|
||||
static enum { in_text, in_data } section = in_text;
|
||||
|
||||
void
|
||||
bc_text ()
|
||||
{
|
||||
section = in_text;
|
||||
}
|
||||
|
||||
void
|
||||
bc_data ()
|
||||
{
|
||||
section = in_data;
|
||||
}
|
||||
|
||||
void
|
||||
bc_align (align)
|
||||
int align;
|
||||
{
|
||||
if (section == in_text)
|
||||
bc_align_const (align);
|
||||
else
|
||||
bc_align_data (align);
|
||||
}
|
||||
|
||||
void
|
||||
bc_emit (data, size)
|
||||
char *data;
|
||||
unsigned int size;
|
||||
{
|
||||
if (section == in_text)
|
||||
bc_emit_const (data, size);
|
||||
else
|
||||
bc_emit_data (data, size);
|
||||
}
|
||||
|
||||
void
|
||||
bc_emit_skip (size)
|
||||
unsigned int size;
|
||||
{
|
||||
if (section == in_text)
|
||||
bc_emit_const_skip (size);
|
||||
else
|
||||
bc_emit_data_skip (size);
|
||||
}
|
||||
|
||||
int
|
||||
bc_emit_labeldef (name)
|
||||
char *name;
|
||||
{
|
||||
if (section == in_text)
|
||||
return bc_emit_const_labeldef (name);
|
||||
else
|
||||
return bc_emit_data_labeldef (name);
|
||||
}
|
||||
|
||||
void
|
||||
bc_emit_labelref (name, offset)
|
||||
char *name;
|
||||
int offset;
|
||||
{
|
||||
if (section == in_text)
|
||||
bc_emit_const_labelref (name, offset);
|
||||
else
|
||||
bc_emit_data_labelref (name, offset);
|
||||
}
|
||||
|
||||
void
|
||||
bc_write_file (file)
|
||||
FILE *file;
|
||||
{
|
||||
BC_WRITE_FILE (file);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new bytecode rtx.
|
||||
If you supply a null BC_LABEL, we generate one. */
|
||||
|
||||
rtx
|
||||
bc_gen_rtx (label, offset, bc_label)
|
||||
char *label;
|
||||
int offset;
|
||||
struct bc_label *bc_label;
|
||||
{
|
||||
rtx r;
|
||||
|
||||
if (bc_label == 0)
|
||||
bc_label = (struct bc_label *) xmalloc (sizeof (struct bc_label));
|
||||
|
||||
r = gen_rtx (CODE_LABEL, VOIDmode, label, bc_label);
|
||||
bc_label->offset = offset;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Print bytecode rtx */
|
||||
void
|
||||
bc_print_rtl (fp, r)
|
||||
FILE *fp;
|
||||
rtx r;
|
||||
{
|
||||
#if 0 /* This needs to get fixed to really work again. */
|
||||
/* BC_WRITE_RTL has a definition
|
||||
that doesn't even make sense for this use. */
|
||||
BC_WRITE_RTL (r, fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Emit a bytecode, keeping a running tally of the stack depth. */
|
||||
void
|
||||
bc_emit_bytecode (bytecode)
|
||||
enum bytecode_opcode bytecode;
|
||||
{
|
||||
char byte;
|
||||
static int prev_lineno = -1;
|
||||
|
||||
byte = (char) bytecode;
|
||||
|
||||
#ifdef BCDEBUG_PRINT_CODE
|
||||
if (lineno != prev_lineno)
|
||||
{
|
||||
fprintf (stderr, "<line %d>\n", lineno);
|
||||
prev_lineno = lineno;
|
||||
}
|
||||
|
||||
fputs (opcode_name[(unsigned int) bytecode], stderr);
|
||||
#endif
|
||||
|
||||
/* Due to errors we are often requested to output bytecodes that
|
||||
will cause an interpreter stack undeflow when executed. Instead of
|
||||
dumping core on such occasions, we omit the bytecode. Erroneous code
|
||||
should not be executed, regardless. This makes life much easier, since
|
||||
we don't have to deceive ourselves about the known stack depth. */
|
||||
|
||||
bc_emit_bytecode_const (&byte, 1);
|
||||
|
||||
if ((stack_depth -= arityvec[(int) bytecode].ninputs) >= 0)
|
||||
{
|
||||
if ((stack_depth += arityvec[(int) bytecode].noutputs) > max_stack_depth)
|
||||
max_stack_depth = stack_depth;
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_STACK_FOR_BC
|
||||
VALIDATE_STACK_FOR_BC ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef BCDEBUG_PRINT_CODE
|
||||
#define PRLIT(TYPE, PTR) fprintf (stderr, " [%x]", *(TYPE *) PTR)
|
||||
#else
|
||||
#define PRLIT(X,Y)
|
||||
#endif
|
||||
|
||||
/* Emit a complete bytecode instruction, expecting the correct number
|
||||
of literal values in the call. First argument is the instruction, the
|
||||
remaining arguments are literals of size HOST_WIDE_INT or smaller. */
|
||||
void
|
||||
bc_emit_instruction VPROTO((enum bytecode_opcode opcode, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
enum bytecode_opcode opcode;
|
||||
#endif
|
||||
va_list arguments;
|
||||
int nliteral, instruction;
|
||||
|
||||
VA_START (arguments, opcode);
|
||||
|
||||
#ifndef __STDC__
|
||||
opcode = va_arg (arguments, enum bytecode_opcode);
|
||||
#endif
|
||||
|
||||
/* Emit instruction bytecode */
|
||||
bc_emit_bytecode (opcode);
|
||||
instruction = (int) opcode;
|
||||
|
||||
/* Loop literals and emit as bytecode constants */
|
||||
for (nliteral = 0; nliteral < arityvec[instruction].nliterals; nliteral++)
|
||||
{
|
||||
switch (arityvec[instruction].literals[nliteral])
|
||||
{
|
||||
/* This conditional is a kludge, but it's necessary
|
||||
because TYPE might be long long. */
|
||||
#ifdef __GNUC__
|
||||
/* Expand definitions into case statements */
|
||||
#define DEFTYPECODE(CODE, NAME, MODE, TYPE) \
|
||||
case CODE: \
|
||||
{ \
|
||||
TYPE temp = va_arg (arguments, TYPE); \
|
||||
bc_emit_bytecode_const ((void *) &temp, sizeof temp); \
|
||||
PRLIT (TYPE, &temp); } \
|
||||
break;
|
||||
|
||||
#include "bc-typecd.def"
|
||||
|
||||
#undef DEFTYPECODE
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BCDEBUG_PRINT_CODE
|
||||
fputc ('\n', stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Emit the machine-code interface trampoline at the beginning of a byte
|
||||
coded function. The argument is a label name of the interpreter
|
||||
bytecode callinfo structure; the return value is a label name for
|
||||
the beginning of the actual bytecode. */
|
||||
char *
|
||||
bc_emit_trampoline (callinfo)
|
||||
char *callinfo;
|
||||
{
|
||||
char mylab[20];
|
||||
static int n;
|
||||
|
||||
sprintf (mylab, "*LB%d", n++);
|
||||
|
||||
BC_EMIT_TRAMPOLINE (trampoline, callinfo);
|
||||
|
||||
seg_defsym (bytecode, mylab);
|
||||
return sym_lookup (mylab)->name;
|
||||
}
|
||||
|
||||
|
||||
/* Simple strdup */
|
||||
char *
|
||||
bc_xstrdup (str)
|
||||
char *str;
|
||||
{
|
||||
char *tmp = xmalloc (strlen (str) + 1);
|
||||
|
||||
strcpy (tmp, str);
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/* bc-emit.h - declare entry points for producing object files of bytecodes. */
|
||||
|
||||
/* Internal format of symbol table for the object file. */
|
||||
struct bc_sym
|
||||
{
|
||||
/* Private copy separately malloc'd. */
|
||||
char *name;
|
||||
|
||||
/* Symbol has a defined value. */
|
||||
unsigned int defined:1;
|
||||
|
||||
/* Symbol has been globalized. */
|
||||
unsigned int global:1;
|
||||
|
||||
/* Symbol is common. */
|
||||
unsigned int common:1;
|
||||
|
||||
/* Value if defined. */
|
||||
unsigned long int val;
|
||||
|
||||
/* Used in internal symbol table structure. */
|
||||
struct bc_sym *next;
|
||||
};
|
||||
|
||||
|
||||
/* List of symbols defined in a particular segment. */
|
||||
struct bc_segsym
|
||||
{
|
||||
struct bc_sym *sym;
|
||||
struct bc_segsym *next;
|
||||
};
|
||||
|
||||
|
||||
/* List of relocations needed in a particular segment. */
|
||||
struct bc_segreloc
|
||||
{
|
||||
/* Offset of datum to be relocated. */
|
||||
unsigned int offset;
|
||||
|
||||
/* Symbol to be relocated by. */
|
||||
struct bc_sym *sym;
|
||||
|
||||
struct bc_segreloc *next;
|
||||
};
|
||||
|
||||
|
||||
/* Segment of an object file. */
|
||||
struct bc_seg
|
||||
{
|
||||
/* Size allocated to contents. */
|
||||
unsigned int alloc;
|
||||
|
||||
/* Pointer to base of contents. */
|
||||
char *data;
|
||||
|
||||
/* Actual size of contents. */
|
||||
unsigned int size;
|
||||
|
||||
/* List of symbols defined in this segment. */
|
||||
struct bc_segsym *syms;
|
||||
|
||||
/* List of relocations for this segment. */
|
||||
struct bc_segreloc *relocs;
|
||||
};
|
||||
|
||||
|
||||
/* Anonymous bytecode label within a single function. */
|
||||
struct bc_label
|
||||
{
|
||||
/* Offset of label from start of segment. */
|
||||
unsigned int offset;
|
||||
|
||||
/* True when offset is valid. */
|
||||
unsigned int defined:1;
|
||||
|
||||
/* Unique bytecode ID, used to determine innermost
|
||||
block containment */
|
||||
int uid;
|
||||
|
||||
/* Next node in list */
|
||||
struct bc_label *next;
|
||||
};
|
||||
|
||||
|
||||
/* Reference to a bc_label; a list of all such references is kept for
|
||||
the function, then when it is finished they are backpatched to
|
||||
contain the correct values. */
|
||||
|
||||
struct bc_labelref
|
||||
{
|
||||
/* Label referenced. */
|
||||
struct bc_label *label;
|
||||
|
||||
/* Code offset of reference. */
|
||||
unsigned int offset;
|
||||
|
||||
/* Next labelref in list */
|
||||
struct bc_labelref *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern void bc_initialize();
|
||||
extern int bc_begin_function();
|
||||
extern char *bc_emit_trampoline();
|
||||
extern void bc_emit_bytecode();
|
||||
extern void bc_emit_bytecode_const();
|
||||
extern struct bc_label *bc_get_bytecode_label();
|
||||
extern int bc_emit_bytecode_labeldef();
|
||||
extern void bc_emit_bytecode_labelref();
|
||||
extern void bc_emit_code_labelref();
|
||||
extern char *bc_end_function();
|
||||
extern void bc_align_const();
|
||||
extern void bc_emit_const();
|
||||
extern void bc_emit_const_skip();
|
||||
extern int bc_emit_const_labeldef();
|
||||
extern void bc_emit_const_labelref();
|
||||
extern void bc_align_data();
|
||||
extern void bc_emit_data();
|
||||
extern void bc_emit_data_skip();
|
||||
extern int bc_emit_data_labeldef();
|
||||
extern void bc_emit_data_labelref();
|
||||
extern int bc_define_pointer ();
|
||||
extern int bc_emit_common();
|
||||
extern void bc_globalize_label();
|
||||
extern void bc_text();
|
||||
extern void bc_data();
|
||||
extern void bc_align();
|
||||
extern void bc_emit();
|
||||
extern void bc_emit_skip();
|
||||
extern int bc_emit_labeldef();
|
||||
extern void bc_emit_labelref();
|
||||
extern void bc_write_file();
|
||||
|
|
@ -1,789 +0,0 @@
|
|||
/* Bytecode conversion definitions for GNU C-compiler.
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "rtl.h"
|
||||
#include "machmode.h"
|
||||
#include "obstack.h"
|
||||
#include "bytecode.h"
|
||||
#include "bc-typecd.h"
|
||||
#include "bc-opcode.h"
|
||||
#include "bc-optab.h"
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
|
||||
extern char *xmalloc ();
|
||||
extern void free ();
|
||||
|
||||
/* Table relating interpreter typecodes to machine modes. */
|
||||
#define GET_TYPECODE_MODE(CODE) (typecode_mode[((int) CODE)])
|
||||
enum machine_mode typecode_mode[] = {
|
||||
#define DEFTYPECODE(CODE, NAME, MODE, TYPE) MODE,
|
||||
#include "bc-typecd.def"
|
||||
#undef DEFTYPECODE
|
||||
};
|
||||
|
||||
/* Machine mode to type code map */
|
||||
static enum typecode signed_mode_to_code_map[MAX_MACHINE_MODE+1];
|
||||
static enum typecode unsigned_mode_to_code_map[MAX_MACHINE_MODE+1];
|
||||
|
||||
#define GET_TYPECODE_SIZE(CODE) GET_MODE_SIZE (GET_TYPECODE_MODE (CODE))
|
||||
|
||||
#define BIG_ARBITRARY_NUMBER 100000
|
||||
|
||||
/* Table of recipes for conversions among scalar types, to be filled
|
||||
in as needed at run time. */
|
||||
static struct conversion_recipe
|
||||
{
|
||||
unsigned char *opcodes; /* Bytecodes to emit in order. */
|
||||
int nopcodes; /* Count of bytecodes. */
|
||||
int cost; /* A rather arbitrary cost function. */
|
||||
} conversion_recipe[NUM_TYPECODES][NUM_TYPECODES];
|
||||
|
||||
/* Binary operator tables. */
|
||||
struct binary_operator optab_plus_expr[] = {
|
||||
{ addSI, SIcode, SIcode, SIcode },
|
||||
{ addDI, DIcode, DIcode, DIcode },
|
||||
{ addSF, SFcode, SFcode, SFcode },
|
||||
{ addDF, DFcode, DFcode, DFcode },
|
||||
{ addXF, XFcode, XFcode, XFcode },
|
||||
{ addPSI, Pcode, Pcode, SIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_minus_expr[] = {
|
||||
{ subSI, SIcode, SIcode, SIcode },
|
||||
{ subDI, DIcode, DIcode, DIcode },
|
||||
{ subSF, SFcode, SFcode, SFcode },
|
||||
{ subDF, DFcode, DFcode, DFcode },
|
||||
{ subXF, XFcode, XFcode, XFcode },
|
||||
{ subPP, SIcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
/* The ordering of the tables for multiplicative operators
|
||||
is such that unsigned operations will be preferred to signed
|
||||
operations when one argument is unsigned. */
|
||||
|
||||
struct binary_operator optab_mult_expr[] = {
|
||||
{ mulSU, SUcode, SUcode, SUcode },
|
||||
{ mulDU, DUcode, DUcode, DUcode },
|
||||
{ mulSI, SIcode, SIcode, SIcode },
|
||||
{ mulDI, DIcode, DIcode, DIcode },
|
||||
{ mulSF, SFcode, SFcode, SFcode },
|
||||
{ mulDF, DFcode, DFcode, DFcode },
|
||||
{ mulXF, XFcode, XFcode, XFcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_trunc_div_expr[] = {
|
||||
{ divSU, SUcode, SUcode, SUcode },
|
||||
{ divDU, DUcode, DUcode, DUcode },
|
||||
{ divSI, SIcode, SIcode, SIcode },
|
||||
{ divDI, DIcode, DIcode, DIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_trunc_mod_expr[] = {
|
||||
{ modSU, SUcode, SUcode, SUcode },
|
||||
{ modDU, DUcode, DUcode, DUcode },
|
||||
{ modSI, SIcode, SIcode, SIcode },
|
||||
{ modDI, DIcode, DIcode, DIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_rdiv_expr[] = {
|
||||
{ divSF, SFcode, SFcode, SFcode },
|
||||
{ divDF, DFcode, DFcode, DFcode },
|
||||
{ divXF, XFcode, XFcode, XFcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_bit_and_expr[] = {
|
||||
{ andSI, SIcode, SIcode, SIcode },
|
||||
{ andDI, DIcode, DIcode, DIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_bit_ior_expr[] = {
|
||||
{ iorSI, SIcode, SIcode, SIcode },
|
||||
{ iorDI, DIcode, DIcode, DIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_bit_xor_expr[] = {
|
||||
{ xorSI, SIcode, SIcode, SIcode },
|
||||
{ xorDI, DIcode, DIcode, DIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_lshift_expr[] = {
|
||||
{ lshiftSI, SIcode, SIcode, SIcode },
|
||||
{ lshiftSU, SUcode, SUcode, SIcode },
|
||||
{ lshiftDI, DIcode, DIcode, SIcode },
|
||||
{ lshiftDU, DUcode, DUcode, SIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_rshift_expr[] = {
|
||||
{ rshiftSI, SIcode, SIcode, SIcode },
|
||||
{ rshiftSU, SUcode, SUcode, SIcode },
|
||||
{ rshiftDI, DIcode, DIcode, SIcode },
|
||||
{ rshiftDU, DUcode, DUcode, SIcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_truth_and_expr[] = {
|
||||
{ andSI, SIcode, Tcode, Tcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_truth_or_expr[] = {
|
||||
{ iorSI, SIcode, Tcode, Tcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_lt_expr[] = {
|
||||
{ ltSI, Tcode, SIcode, SIcode },
|
||||
{ ltSU, Tcode, SUcode, SUcode },
|
||||
{ ltDI, Tcode, DIcode, DIcode },
|
||||
{ ltDU, Tcode, DUcode, DUcode },
|
||||
{ ltSF, Tcode, SFcode, SFcode },
|
||||
{ ltDF, Tcode, DFcode, DFcode },
|
||||
{ ltXF, Tcode, XFcode, XFcode },
|
||||
{ ltP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_le_expr[] = {
|
||||
{ leSI, Tcode, SIcode, SIcode },
|
||||
{ leSU, Tcode, SUcode, SUcode },
|
||||
{ leDI, Tcode, DIcode, DIcode },
|
||||
{ leDU, Tcode, DUcode, DUcode },
|
||||
{ leSF, Tcode, SFcode, SFcode },
|
||||
{ leDF, Tcode, DFcode, DFcode },
|
||||
{ leXF, Tcode, XFcode, XFcode },
|
||||
{ leP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_ge_expr[] = {
|
||||
{ geSI, Tcode, SIcode, SIcode },
|
||||
{ geSU, Tcode, SUcode, SUcode },
|
||||
{ geDI, Tcode, DIcode, DIcode },
|
||||
{ geDU, Tcode, DUcode, DUcode },
|
||||
{ geSF, Tcode, SFcode, SFcode },
|
||||
{ geDF, Tcode, DFcode, DFcode },
|
||||
{ geXF, Tcode, XFcode, XFcode },
|
||||
{ geP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_gt_expr[] = {
|
||||
{ gtSI, Tcode, SIcode, SIcode },
|
||||
{ gtSU, Tcode, SUcode, SUcode },
|
||||
{ gtDI, Tcode, DIcode, DIcode },
|
||||
{ gtDU, Tcode, DUcode, DUcode },
|
||||
{ gtSF, Tcode, SFcode, SFcode },
|
||||
{ gtDF, Tcode, DFcode, DFcode },
|
||||
{ gtXF, Tcode, XFcode, XFcode },
|
||||
{ gtP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_eq_expr[] = {
|
||||
{ eqSI, Tcode, SIcode, SIcode },
|
||||
{ eqDI, Tcode, DIcode, DIcode },
|
||||
{ eqSF, Tcode, SFcode, SFcode },
|
||||
{ eqDF, Tcode, DFcode, DFcode },
|
||||
{ eqXF, Tcode, XFcode, XFcode },
|
||||
{ eqP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct binary_operator optab_ne_expr[] = {
|
||||
{ neSI, Tcode, SIcode, SIcode },
|
||||
{ neDI, Tcode, DIcode, DIcode },
|
||||
{ neSF, Tcode, SFcode, SFcode },
|
||||
{ neDF, Tcode, DFcode, DFcode },
|
||||
{ neXF, Tcode, XFcode, XFcode },
|
||||
{ neP, Tcode, Pcode, Pcode },
|
||||
{ -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
/* Unary operator tables. */
|
||||
struct unary_operator optab_negate_expr[] = {
|
||||
{ negSI, SIcode, SIcode },
|
||||
{ negDI, DIcode, DIcode },
|
||||
{ negSF, SFcode, SFcode },
|
||||
{ negDF, DFcode, DFcode },
|
||||
{ negXF, XFcode, XFcode },
|
||||
{ -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct unary_operator optab_bit_not_expr[] = {
|
||||
{ notSI, SIcode, SIcode },
|
||||
{ notDI, DIcode, DIcode },
|
||||
{ -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct unary_operator optab_truth_not_expr[] = {
|
||||
{ notT, SIcode, SIcode },
|
||||
{ -1, -1, -1 },
|
||||
};
|
||||
|
||||
/* Increment operator tables. */
|
||||
struct increment_operator optab_predecrement_expr[] = {
|
||||
{ predecQI, QIcode },
|
||||
{ predecQI, QUcode },
|
||||
{ predecHI, HIcode },
|
||||
{ predecHI, HUcode },
|
||||
{ predecSI, SIcode },
|
||||
{ predecSI, SUcode },
|
||||
{ predecDI, DIcode },
|
||||
{ predecDI, DUcode },
|
||||
{ predecP, Pcode },
|
||||
{ predecSF, SFcode },
|
||||
{ predecDF, DFcode },
|
||||
{ predecXF, XFcode },
|
||||
{ -1, -1 },
|
||||
};
|
||||
|
||||
struct increment_operator optab_preincrement_expr[] = {
|
||||
{ preincQI, QIcode },
|
||||
{ preincQI, QUcode },
|
||||
{ preincHI, HIcode },
|
||||
{ preincHI, HUcode },
|
||||
{ preincSI, SIcode },
|
||||
{ preincSI, SUcode },
|
||||
{ preincDI, DIcode },
|
||||
{ preincDI, DUcode },
|
||||
{ preincP, Pcode },
|
||||
{ preincSF, SFcode },
|
||||
{ preincDF, DFcode },
|
||||
{ preincXF, XFcode },
|
||||
{ -1, -1 },
|
||||
};
|
||||
|
||||
struct increment_operator optab_postdecrement_expr[] = {
|
||||
{ postdecQI, QIcode },
|
||||
{ postdecQI, QUcode },
|
||||
{ postdecHI, HIcode },
|
||||
{ postdecHI, HUcode },
|
||||
{ postdecSI, SIcode },
|
||||
{ postdecSI, SUcode },
|
||||
{ postdecDI, DIcode },
|
||||
{ postdecDI, DUcode },
|
||||
{ postdecP, Pcode },
|
||||
{ postdecSF, SFcode },
|
||||
{ postdecDF, DFcode },
|
||||
{ postdecXF, XFcode },
|
||||
{ -1, -1 },
|
||||
};
|
||||
|
||||
struct increment_operator optab_postincrement_expr[] = {
|
||||
{ postincQI, QIcode },
|
||||
{ postincQI, QUcode },
|
||||
{ postincHI, HIcode },
|
||||
{ postincHI, HUcode },
|
||||
{ postincSI, SIcode },
|
||||
{ postincSI, SUcode },
|
||||
{ postincDI, DIcode },
|
||||
{ postincDI, DUcode },
|
||||
{ postincP, Pcode },
|
||||
{ postincSF, SFcode },
|
||||
{ postincDF, DFcode },
|
||||
{ postincXF, XFcode },
|
||||
{ -1, -1 },
|
||||
};
|
||||
|
||||
/* Table of conversions supported by the interpreter. */
|
||||
static struct conversion_info
|
||||
{
|
||||
enum bytecode_opcode opcode; /* here indicates the conversion needs no opcode. */
|
||||
enum typecode from;
|
||||
enum typecode to;
|
||||
int cost; /* 1 for no-op conversions, 2 for widening conversions,
|
||||
4 for int/float conversions, 8 for narrowing conversions. */
|
||||
} conversion_info[] = {
|
||||
{ -1, QIcode, QUcode, 1 },
|
||||
{ -1, HIcode, HUcode, 1 },
|
||||
{ -1, SIcode, SUcode, 1 },
|
||||
{ -1, DIcode, DUcode, 1 },
|
||||
{ -1, QUcode, QIcode, 1 },
|
||||
{ -1, HUcode, HIcode, 1 },
|
||||
{ -1, SUcode, SIcode, 1 },
|
||||
{ -1, DUcode, DIcode, 1 },
|
||||
{ -1, Tcode, SIcode, 1 },
|
||||
{ convertQIHI, QIcode, HIcode, 2 },
|
||||
{ convertQUHU, QUcode, HUcode, 2 },
|
||||
{ convertQUSU, QUcode, SUcode, 2 },
|
||||
{ convertHISI, HIcode, SIcode, 2 },
|
||||
{ convertHUSU, HUcode, SUcode, 2 },
|
||||
{ convertSIDI, SIcode, DIcode, 2 },
|
||||
{ convertSUDU, SUcode, DUcode, 2 },
|
||||
{ convertSFDF, SFcode, DFcode, 2 },
|
||||
{ convertDFXF, DFcode, XFcode, 2 },
|
||||
{ convertHIQI, HIcode, QIcode, 8 },
|
||||
{ convertSIQI, SIcode, QIcode, 8 },
|
||||
{ convertSIHI, SIcode, HIcode, 8 },
|
||||
{ convertSUQU, SUcode, QUcode, 8 },
|
||||
{ convertDISI, DIcode, SIcode, 8 },
|
||||
{ convertDFSF, DFcode, SFcode, 8 },
|
||||
{ convertXFDF, XFcode, DFcode, 8 },
|
||||
{ convertPSI, Pcode, SIcode, 2 },
|
||||
{ convertSIP, SIcode, Pcode, 2 },
|
||||
{ convertSIT, SIcode, Tcode, 2 },
|
||||
{ convertDIT, DIcode, Tcode, 2 },
|
||||
{ convertSFT, SFcode, Tcode, 2 },
|
||||
{ convertDFT, DFcode, Tcode, 2 },
|
||||
{ convertXFT, XFcode, Tcode, 2 },
|
||||
{ convertQISI, QIcode, SIcode, 2 },
|
||||
{ convertPT, Pcode, Tcode, 2 },
|
||||
{ convertSISF, SIcode, SFcode, 4 },
|
||||
{ convertSIDF, SIcode, DFcode, 4 },
|
||||
{ convertSIXF, SIcode, XFcode, 4 },
|
||||
{ convertSUSF, SUcode, SFcode, 4 },
|
||||
{ convertSUDF, SUcode, DFcode, 4 },
|
||||
{ convertSUXF, SUcode, XFcode, 4 },
|
||||
{ convertDISF, DIcode, SFcode, 4 },
|
||||
{ convertDIDF, DIcode, DFcode, 4 },
|
||||
{ convertDIXF, DIcode, XFcode, 4 },
|
||||
{ convertDUSF, DUcode, SFcode, 4 },
|
||||
{ convertDUDF, DUcode, DFcode, 4 },
|
||||
{ convertDUXF, DUcode, XFcode, 4 },
|
||||
{ convertSFSI, SFcode, SIcode, 4 },
|
||||
{ convertDFSI, DFcode, SIcode, 4 },
|
||||
{ convertXFSI, XFcode, SIcode, 4 },
|
||||
{ convertSFSU, SFcode, SUcode, 4 },
|
||||
{ convertDFSU, DFcode, SUcode, 4 },
|
||||
{ convertXFSU, XFcode, SUcode, 4 },
|
||||
{ convertSFDI, SFcode, DIcode, 4 },
|
||||
{ convertDFDI, DFcode, DIcode, 4 },
|
||||
{ convertXFDI, XFcode, DIcode, 4 },
|
||||
{ convertSFDU, SFcode, DUcode, 4 },
|
||||
{ convertDFDU, DFcode, DUcode, 4 },
|
||||
{ convertXFDU, XFcode, DUcode, 4 },
|
||||
{ convertSIQI, SIcode, QIcode, 8 },
|
||||
};
|
||||
|
||||
#define NUM_CONVERSIONS (sizeof conversion_info / sizeof (struct conversion_info))
|
||||
|
||||
/* List form of a conversion recipe. */
|
||||
struct conversion_list
|
||||
{
|
||||
enum bytecode_opcode opcode;
|
||||
enum typecode to;
|
||||
int cost;
|
||||
struct conversion_list *prev;
|
||||
};
|
||||
|
||||
/* Determine if it is "reasonable" to add a given conversion to
|
||||
a given list of conversions. The following criteria define
|
||||
"reasonable" conversion lists:
|
||||
* No typecode appears more than once in the sequence (no loops).
|
||||
* At most one conversion from integer to float or vice versa is present.
|
||||
* Either sign extensions or zero extensions may be present, but not both.
|
||||
* No widening conversions occur after a signed/unsigned conversion.
|
||||
* The sequence of sizes must be strict nonincreasing or nondecreasing. */
|
||||
static int
|
||||
conversion_reasonable_p (conversion, list)
|
||||
struct conversion_info *conversion;
|
||||
struct conversion_list *list;
|
||||
{
|
||||
struct conversion_list *curr;
|
||||
int curr_size, prev_size;
|
||||
int has_int_float, has_float_int;
|
||||
int has_sign_extend, has_zero_extend;
|
||||
int has_signed_unsigned, has_unsigned_signed;
|
||||
|
||||
has_int_float = 0;
|
||||
has_float_int = 0;
|
||||
has_sign_extend = 0;
|
||||
has_zero_extend = 0;
|
||||
has_signed_unsigned = 0;
|
||||
has_unsigned_signed = 0;
|
||||
|
||||
/* Make sure the destination typecode doesn't already appear in
|
||||
the list. */
|
||||
for (curr = list; curr; curr = curr->prev)
|
||||
if (conversion->to == curr->to)
|
||||
return 0;
|
||||
|
||||
/* Check for certain kinds of conversions. */
|
||||
if (TYPECODE_INTEGER_P (conversion->from)
|
||||
&& TYPECODE_FLOAT_P (conversion->to))
|
||||
has_int_float = 1;
|
||||
if (TYPECODE_FLOAT_P (conversion->from)
|
||||
&& TYPECODE_INTEGER_P (conversion->to))
|
||||
has_float_int = 1;
|
||||
if (TYPECODE_SIGNED_P (conversion->from)
|
||||
&& TYPECODE_SIGNED_P (conversion->to)
|
||||
&& GET_TYPECODE_SIZE (conversion->from)
|
||||
< GET_TYPECODE_SIZE (conversion->to))
|
||||
has_sign_extend = 1;
|
||||
if (TYPECODE_UNSIGNED_P (conversion->from)
|
||||
&& TYPECODE_UNSIGNED_P (conversion->to)
|
||||
&& GET_TYPECODE_SIZE (conversion->from)
|
||||
< GET_TYPECODE_SIZE (conversion->to))
|
||||
has_zero_extend = 1;
|
||||
|
||||
for (curr = list; curr && curr->prev; curr = curr->prev)
|
||||
{
|
||||
if (TYPECODE_INTEGER_P (curr->prev->to)
|
||||
&& TYPECODE_FLOAT_P (curr->to))
|
||||
has_int_float = 1;
|
||||
if (TYPECODE_FLOAT_P (curr->prev->to)
|
||||
&& TYPECODE_INTEGER_P (curr->to))
|
||||
has_float_int = 1;
|
||||
if (TYPECODE_SIGNED_P (curr->prev->to)
|
||||
&& TYPECODE_SIGNED_P (curr->to)
|
||||
&& GET_TYPECODE_SIZE (curr->prev->to)
|
||||
< GET_TYPECODE_SIZE (curr->to))
|
||||
has_sign_extend = 1;
|
||||
if (TYPECODE_UNSIGNED_P (curr->prev->to)
|
||||
&& TYPECODE_UNSIGNED_P (curr->to)
|
||||
&& GET_TYPECODE_SIZE (curr->prev->to)
|
||||
< GET_TYPECODE_SIZE (curr->to))
|
||||
has_zero_extend = 1;
|
||||
if (TYPECODE_SIGNED_P (curr->prev->to)
|
||||
&& TYPECODE_UNSIGNED_P (curr->to))
|
||||
has_signed_unsigned = 1;
|
||||
if (TYPECODE_UNSIGNED_P (curr->prev->to)
|
||||
&& TYPECODE_SIGNED_P (curr->to))
|
||||
has_unsigned_signed = 1;
|
||||
}
|
||||
|
||||
if (TYPECODE_INTEGER_P (conversion->from)
|
||||
&& TYPECODE_INTEGER_P (conversion->to)
|
||||
&& GET_TYPECODE_SIZE (conversion->to)
|
||||
> GET_TYPECODE_SIZE (conversion->from)
|
||||
&& (has_signed_unsigned || has_unsigned_signed))
|
||||
return 0;
|
||||
|
||||
if (has_float_int && has_int_float || has_sign_extend && has_zero_extend)
|
||||
return 0;
|
||||
|
||||
/* Make sure the sequence of destination typecode sizes is
|
||||
strictly nondecreasing or strictly nonincreasing. */
|
||||
prev_size = GET_TYPECODE_SIZE (conversion->to);
|
||||
for (curr = list; curr; curr = curr->prev)
|
||||
{
|
||||
curr_size = GET_TYPECODE_SIZE (curr->to);
|
||||
if (curr_size != prev_size)
|
||||
break;
|
||||
}
|
||||
if (!curr)
|
||||
return 1;
|
||||
|
||||
if (curr_size < prev_size)
|
||||
for (prev_size = curr_size; curr; curr = curr->prev)
|
||||
{
|
||||
curr_size = GET_TYPECODE_SIZE (curr->to);
|
||||
if (curr_size > prev_size)
|
||||
return 0;
|
||||
prev_size = curr_size;
|
||||
}
|
||||
else
|
||||
for (prev_size = curr_size; curr; curr = curr->prev)
|
||||
{
|
||||
curr_size = GET_TYPECODE_SIZE (curr->to);
|
||||
if (curr_size < prev_size)
|
||||
return 0;
|
||||
prev_size = curr_size;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Exhaustively search all reasonable conversions to find one to
|
||||
convert the given types. */
|
||||
static struct conversion_recipe
|
||||
deduce_conversion (from, to)
|
||||
enum typecode from, to;
|
||||
{
|
||||
struct rl
|
||||
{
|
||||
struct conversion_list *list;
|
||||
struct rl *next;
|
||||
} *prev, curr, *good, *temp;
|
||||
struct conversion_list *conv, *best;
|
||||
int i, cost, bestcost;
|
||||
struct conversion_recipe result;
|
||||
struct obstack recipe_obstack;
|
||||
|
||||
|
||||
obstack_init (&recipe_obstack);
|
||||
curr.next = (struct rl *) obstack_alloc (&recipe_obstack, sizeof (struct rl));
|
||||
curr.next->list =
|
||||
(struct conversion_list *) obstack_alloc (&recipe_obstack,
|
||||
sizeof (struct conversion_list));
|
||||
curr.next->list->opcode = -1;
|
||||
curr.next->list->to = from;
|
||||
curr.next->list->cost = 0;
|
||||
curr.next->list->prev = 0;
|
||||
curr.next->next = 0;
|
||||
good = 0;
|
||||
|
||||
while (curr.next)
|
||||
{
|
||||
/* Remove successful conversions from further consideration. */
|
||||
for (prev = &curr; prev; prev = prev->next)
|
||||
if (prev->next && prev->next->list->to == to)
|
||||
{
|
||||
temp = prev->next->next;
|
||||
prev->next->next = good;
|
||||
good = prev->next;
|
||||
prev->next = temp;
|
||||
}
|
||||
|
||||
/* Go through each of the pending conversion chains, trying
|
||||
all possible candidate conversions on them. */
|
||||
for (prev = curr.next, curr.next = 0; prev; prev = prev->next)
|
||||
for (i = 0; i < NUM_CONVERSIONS; ++i)
|
||||
if (conversion_info[i].from == prev->list->to
|
||||
&& conversion_reasonable_p (&conversion_info[i], prev->list))
|
||||
{
|
||||
temp = (struct rl *) obstack_alloc (&recipe_obstack,
|
||||
sizeof (struct rl));
|
||||
temp->list = (struct conversion_list *)
|
||||
obstack_alloc (&recipe_obstack,
|
||||
sizeof (struct conversion_list));
|
||||
temp->list->opcode = conversion_info[i].opcode;
|
||||
temp->list->to = conversion_info[i].to;
|
||||
temp->list->cost = conversion_info[i].cost;
|
||||
temp->list->prev = prev->list;
|
||||
temp->next = curr.next;
|
||||
curr.next = temp;
|
||||
}
|
||||
}
|
||||
|
||||
bestcost = BIG_ARBITRARY_NUMBER;
|
||||
best = 0;
|
||||
for (temp = good; temp; temp = temp->next)
|
||||
{
|
||||
for (conv = temp->list, cost = 0; conv; conv = conv->prev)
|
||||
cost += conv->cost;
|
||||
if (cost < bestcost)
|
||||
{
|
||||
bestcost = cost;
|
||||
best = temp->list;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best)
|
||||
abort ();
|
||||
|
||||
for (i = 0, conv = best; conv; conv = conv->prev)
|
||||
if (conv->opcode != -1)
|
||||
++i;
|
||||
|
||||
result.opcodes = (unsigned char *) xmalloc (i);
|
||||
result.nopcodes = i;
|
||||
for (conv = best; conv; conv = conv->prev)
|
||||
if (conv->opcode != -1)
|
||||
result.opcodes[--i] = conv->opcode;
|
||||
result.cost = bestcost;
|
||||
obstack_free (&recipe_obstack, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define DEDUCE_CONVERSION(FROM, TO) \
|
||||
(conversion_recipe[(int) FROM][(int) TO].opcodes ? 0 \
|
||||
: (conversion_recipe[(int) FROM][(int) TO] \
|
||||
= deduce_conversion (FROM, TO), 0))
|
||||
|
||||
|
||||
/* Emit a conversion between the given scalar types. */
|
||||
void
|
||||
emit_typecode_conversion (from, to)
|
||||
enum typecode from, to;
|
||||
{
|
||||
int i;
|
||||
|
||||
DEDUCE_CONVERSION (from, to);
|
||||
for (i = 0; i < conversion_recipe[(int) from][(int) to].nopcodes; ++i)
|
||||
bc_emit_instruction (conversion_recipe[(int) from][(int) to].opcodes[i]);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize mode_to_code_map[] */
|
||||
void
|
||||
bc_init_mode_to_code_map ()
|
||||
{
|
||||
int mode;
|
||||
|
||||
for (mode = 0; mode < MAX_MACHINE_MODE + 1; mode++)
|
||||
{
|
||||
signed_mode_to_code_map[mode] =
|
||||
unsigned_mode_to_code_map[mode] =
|
||||
LAST_AND_UNUSED_TYPECODE;
|
||||
}
|
||||
|
||||
#define DEF_MODEMAP(SYM, CODE, UCODE, CONST, LOAD, STORE) \
|
||||
{ signed_mode_to_code_map[(int) SYM] = CODE; \
|
||||
unsigned_mode_to_code_map[(int) SYM] = UCODE; }
|
||||
#include "modemap.def"
|
||||
#undef DEF_MODEMAP
|
||||
|
||||
/* Initialize opcode maps for const, load, and store */
|
||||
bc_init_mode_to_opcode_maps ();
|
||||
}
|
||||
|
||||
/* Given a machine mode return the preferred typecode. */
|
||||
enum typecode
|
||||
preferred_typecode (mode, unsignedp)
|
||||
enum machine_mode mode;
|
||||
int unsignedp;
|
||||
{
|
||||
enum typecode code = (unsignedp
|
||||
? unsigned_mode_to_code_map
|
||||
: signed_mode_to_code_map) [MIN ((int) mode,
|
||||
(int) MAX_MACHINE_MODE)];
|
||||
|
||||
if (code == LAST_AND_UNUSED_TYPECODE)
|
||||
abort ();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/* Expand a conversion between the given types. */
|
||||
void
|
||||
bc_expand_conversion (from, to)
|
||||
tree from, to;
|
||||
{
|
||||
enum typecode fcode, tcode;
|
||||
|
||||
fcode = preferred_typecode (TYPE_MODE (from), TREE_UNSIGNED (from));
|
||||
tcode = preferred_typecode (TYPE_MODE (to), TREE_UNSIGNED (to));
|
||||
|
||||
emit_typecode_conversion (fcode, tcode);
|
||||
}
|
||||
|
||||
/* Expand a conversion of the given type to a truth value. */
|
||||
void
|
||||
bc_expand_truth_conversion (from)
|
||||
tree from;
|
||||
{
|
||||
enum typecode fcode;
|
||||
|
||||
fcode = preferred_typecode (TYPE_MODE (from), TREE_UNSIGNED (from));
|
||||
emit_typecode_conversion (fcode, Tcode);
|
||||
}
|
||||
|
||||
/* Emit an appropriate binary operation. */
|
||||
void
|
||||
bc_expand_binary_operation (optab, resulttype, arg0, arg1)
|
||||
struct binary_operator optab[];
|
||||
tree resulttype, arg0, arg1;
|
||||
{
|
||||
int i, besti, cost, bestcost;
|
||||
enum typecode resultcode, arg0code, arg1code;
|
||||
|
||||
resultcode = preferred_typecode (TYPE_MODE (resulttype), TREE_UNSIGNED (resulttype));
|
||||
arg0code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg0)), TREE_UNSIGNED (resulttype));
|
||||
arg1code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg1)), TREE_UNSIGNED (resulttype));
|
||||
|
||||
besti = -1;
|
||||
bestcost = BIG_ARBITRARY_NUMBER;
|
||||
|
||||
for (i = 0; optab[i].opcode != -1; ++i)
|
||||
{
|
||||
cost = 0;
|
||||
DEDUCE_CONVERSION (arg0code, optab[i].arg0);
|
||||
cost += conversion_recipe[(int) arg0code][(int) optab[i].arg0].cost;
|
||||
DEDUCE_CONVERSION (arg1code, optab[i].arg1);
|
||||
cost += conversion_recipe[(int) arg1code][(int) optab[i].arg1].cost;
|
||||
if (cost < bestcost)
|
||||
{
|
||||
besti = i;
|
||||
bestcost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
if (besti == -1)
|
||||
abort ();
|
||||
|
||||
expand_expr (arg1, 0, VOIDmode, 0);
|
||||
emit_typecode_conversion (arg1code, optab[besti].arg1);
|
||||
expand_expr (arg0, 0, VOIDmode, 0);
|
||||
emit_typecode_conversion (arg0code, optab[besti].arg0);
|
||||
bc_emit_instruction (optab[besti].opcode);
|
||||
emit_typecode_conversion (optab[besti].result, resultcode);
|
||||
}
|
||||
|
||||
/* Emit an appropriate unary operation. */
|
||||
void
|
||||
bc_expand_unary_operation (optab, resulttype, arg0)
|
||||
struct unary_operator optab[];
|
||||
tree resulttype, arg0;
|
||||
{
|
||||
int i, besti, cost, bestcost;
|
||||
enum typecode resultcode, arg0code;
|
||||
|
||||
resultcode = preferred_typecode (TYPE_MODE (resulttype), TREE_UNSIGNED (resulttype));
|
||||
arg0code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg0)), TREE_UNSIGNED (TREE_TYPE (arg0)));
|
||||
|
||||
besti = -1;
|
||||
bestcost = BIG_ARBITRARY_NUMBER;
|
||||
|
||||
for (i = 0; optab[i].opcode != -1; ++i)
|
||||
{
|
||||
DEDUCE_CONVERSION (arg0code, optab[i].arg0);
|
||||
cost = conversion_recipe[(int) arg0code][(int) optab[i].arg0].cost;
|
||||
if (cost < bestcost)
|
||||
{
|
||||
besti = i;
|
||||
bestcost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
if (besti == -1)
|
||||
abort ();
|
||||
|
||||
expand_expr (arg0, 0, VOIDmode, 0);
|
||||
emit_typecode_conversion (arg0code, optab[besti].arg0);
|
||||
bc_emit_instruction (optab[besti].opcode);
|
||||
emit_typecode_conversion (optab[besti].result, resultcode);
|
||||
}
|
||||
|
||||
|
||||
/* Emit an appropriate increment. */
|
||||
void
|
||||
bc_expand_increment (optab, type)
|
||||
struct increment_operator optab[];
|
||||
tree type;
|
||||
{
|
||||
enum typecode code;
|
||||
int i;
|
||||
|
||||
code = preferred_typecode (TYPE_MODE (type), TREE_UNSIGNED (type));
|
||||
for (i = 0; (int) optab[i].opcode >= 0; ++i)
|
||||
if (code == optab[i].arg)
|
||||
{
|
||||
bc_emit_instruction (optab[i].opcode);
|
||||
return;
|
||||
}
|
||||
abort ();
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* Bytecode token definitions for GNU C-compiler.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
extern void bc_expand_conversion ();
|
||||
extern void bc_expand_truth_conversion ();
|
||||
extern void bc_expand_binary_operation ();
|
||||
extern void bc_expand_unary_operation ();
|
||||
|
||||
struct binary_operator
|
||||
{
|
||||
enum bytecode_opcode opcode;
|
||||
enum typecode result;
|
||||
enum typecode arg0;
|
||||
enum typecode arg1;
|
||||
};
|
||||
|
||||
extern struct binary_operator optab_plus_expr[];
|
||||
extern struct binary_operator optab_minus_expr[];
|
||||
extern struct binary_operator optab_mult_expr[];
|
||||
extern struct binary_operator optab_trunc_div_expr[];
|
||||
extern struct binary_operator optab_trunc_mod_expr[];
|
||||
extern struct binary_operator optab_rdiv_expr[];
|
||||
extern struct binary_operator optab_bit_and_expr[];
|
||||
extern struct binary_operator optab_bit_ior_expr[];
|
||||
extern struct binary_operator optab_bit_xor_expr[];
|
||||
extern struct binary_operator optab_lshift_expr[];
|
||||
extern struct binary_operator optab_rshift_expr[];
|
||||
extern struct binary_operator optab_truth_and_expr[];
|
||||
extern struct binary_operator optab_truth_or_expr[];
|
||||
extern struct binary_operator optab_lt_expr[];
|
||||
extern struct binary_operator optab_le_expr[];
|
||||
extern struct binary_operator optab_ge_expr[];
|
||||
extern struct binary_operator optab_gt_expr[];
|
||||
extern struct binary_operator optab_eq_expr[];
|
||||
extern struct binary_operator optab_ne_expr[];
|
||||
|
||||
struct unary_operator
|
||||
{
|
||||
enum bytecode_opcode opcode;
|
||||
enum typecode result;
|
||||
enum typecode arg0;
|
||||
};
|
||||
|
||||
extern struct unary_operator optab_negate_expr[];
|
||||
extern struct unary_operator optab_bit_not_expr[];
|
||||
extern struct unary_operator optab_truth_not_expr[];
|
||||
|
||||
struct increment_operator
|
||||
{
|
||||
enum bytecode_opcode opcode;
|
||||
enum typecode arg;
|
||||
};
|
||||
|
||||
extern struct increment_operator optab_predecrement_expr[];
|
||||
extern struct increment_operator optab_preincrement_expr[];
|
||||
extern struct increment_operator optab_postdecrement_expr[];
|
||||
extern struct increment_operator optab_postincrement_expr[];
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/* Typecodes used by the interpreter and their related
|
||||
machine modes and types.
|
||||
|
||||
The last argument is used for retrieving the given
|
||||
type from a varargs list. Due to a bug in varargs,
|
||||
the type has to be the generic machine type of
|
||||
larger. */
|
||||
|
||||
DEFTYPECODE (QIcode, "QI", QImode, SItype)
|
||||
DEFTYPECODE (QUcode, "QU", QImode, SUtype)
|
||||
DEFTYPECODE (HIcode, "HI", HImode, SItype)
|
||||
DEFTYPECODE (HUcode, "HU", HImode, SUtype)
|
||||
DEFTYPECODE (SIcode, "SI", SImode, SItype)
|
||||
DEFTYPECODE (SUcode, "SU", SImode, SUtype)
|
||||
DEFTYPECODE (DIcode, "DI", DImode, DItype)
|
||||
DEFTYPECODE (DUcode, "DU", DImode, DUtype)
|
||||
DEFTYPECODE (SFcode, "SF", SFmode, SFtype)
|
||||
DEFTYPECODE (DFcode, "DF", DFmode, DFtype)
|
||||
DEFTYPECODE (XFcode, "XF", XFmode, XFtype)
|
||||
DEFTYPECODE (Pcode, "P", PSImode, Ptype)
|
||||
DEFTYPECODE (Tcode, "T", SImode, SItype)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/* Typecode definitions for Bytecode Interpreter.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef TYPECODE_H
|
||||
#define TYPECODE_H
|
||||
|
||||
enum typecode
|
||||
{
|
||||
#define DEFTYPECODE(CODE, NAME, MACHMODE, TYPE) CODE,
|
||||
#include "bc-typecd.def"
|
||||
#undef DEFTYPECODE
|
||||
|
||||
LAST_AND_UNUSED_TYPECODE
|
||||
};
|
||||
|
||||
/* Determine if a given type is integer. */
|
||||
#define TYPECODE_INTEGER_P(TYPECODE) ((int) (TYPECODE) < (int) SFcode)
|
||||
|
||||
/* Determine if a given type is unsigned. */
|
||||
#define TYPECODE_UNSIGNED_P(TYPECODE) \
|
||||
(TYPECODE_INTEGER_P(TYPECODE) && (int) (TYPECODE) & 1)
|
||||
|
||||
/* Determine if a given type is signed. */
|
||||
#define TYPECODE_SIGNED_P(TYPECODE) \
|
||||
(TYPECODE_INTEGER_P(TYPECODE) && !((int) (TYPECODE) & 1))
|
||||
|
||||
/* Determine if a given type is floating. */
|
||||
#define TYPECODE_FLOAT_P(TYPECODE) \
|
||||
((int) (TYPECODE) < (int) Pcode && !TYPECODE_INTEGER_P(TYPECODE))
|
||||
|
||||
/* Determine if the given type is arithmetic. */
|
||||
#define TYPECODE_ARITH_P(TYPECODE) \
|
||||
(TYPECODE_INTEGER_P(TYPECODE) || TYPECODE_FLOAT_P(TYPECODE))
|
||||
|
||||
#define NUM_TYPECODES ((int) LAST_AND_UNUSED_TYPECODE)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/* Bytecode Interpreter utility to generate arity table.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hconfig.h"
|
||||
#include "bi-defs.h"
|
||||
|
||||
int
|
||||
length (n)
|
||||
struct node *n;
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; n; n = n->next)
|
||||
++k;
|
||||
return k;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct def *d;
|
||||
struct variation *v;
|
||||
struct node *n;
|
||||
|
||||
yyparse ();
|
||||
reverse ();
|
||||
|
||||
for (d = defs; d; d = d->next)
|
||||
for (v = d->variations; v; v = v->next)
|
||||
{
|
||||
printf ("{ %d, %d, %d, {", length (v->inputs),
|
||||
length (v->outputs), length (v->literals));
|
||||
for (n = v->literals; n; n = n->next)
|
||||
printf ("(char) %scode, ", n->text);
|
||||
if (v->literals == 0)
|
||||
printf ("0");
|
||||
printf ("}},\n");
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
|
||||
memory. */
|
||||
char *
|
||||
xmalloc (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *tmp = (char *) malloc (nbytes);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* Definitions for Bytecode Interpreter.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
struct node
|
||||
{
|
||||
char *text;
|
||||
struct node *next;
|
||||
};
|
||||
|
||||
struct variation
|
||||
{
|
||||
char *name;
|
||||
int code;
|
||||
struct node *inputs;
|
||||
struct node *outputs;
|
||||
struct node *literals;
|
||||
struct variation *next;
|
||||
};
|
||||
|
||||
struct def
|
||||
{
|
||||
char *basename;
|
||||
char *template;
|
||||
struct variation *variations;
|
||||
struct def *next;
|
||||
};
|
||||
|
||||
extern struct def *defs;
|
||||
extern int ndefs;
|
||||
extern void reverse();
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
/* Lexer for scanner of bytecode definition file.
|
||||
Copyright (C) 1993, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hconfig.h"
|
||||
#include "bi-parser.h"
|
||||
|
||||
|
||||
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
|
||||
memory. */
|
||||
|
||||
static char *
|
||||
xmalloc (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *tmp = (char *) malloc (nbytes);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/* Safely reallocate BLOCK so its size becomes NBYTES.
|
||||
The block returned may be different from the one supplied. */
|
||||
|
||||
static char *
|
||||
xrealloc (block, nbytes)
|
||||
char *block;
|
||||
int nbytes;
|
||||
{
|
||||
char *tmp = (block
|
||||
? (char *) realloc (block, nbytes)
|
||||
: (char *) malloc (nbytes));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
fprintf (stderr, "can't reallocate %d bytes (out of virtual memory)\n", nbytes);
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/* Scan for string token on standard input. A string is, for our
|
||||
purposes here, a sequence of characters that starts with the regexp
|
||||
``[^ #\t\n(),]'' and is then followed by the regexp ``[^#(),]*''. Any
|
||||
character is accepted if preceded by a backslash, "\\". It is assumed
|
||||
that the first character has already been checked by the main loop. */
|
||||
|
||||
static char *
|
||||
scan_string ()
|
||||
{
|
||||
char *buffer = NULL;
|
||||
char *point = NULL;
|
||||
int buffer_size = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getc (stdin)) != EOF
|
||||
&& c != '#' && c != '(' && c != ')' && c != ',')
|
||||
{
|
||||
/* Extend buffer, if necessary (minus two so there's room for the NUL
|
||||
trailer as well as another character if this one is a backslash). */
|
||||
if (!buffer_size || (point - buffer >= buffer_size-2))
|
||||
{
|
||||
int previous_point_index = point - buffer;
|
||||
|
||||
buffer_size = (!buffer_size ? 32 : buffer_size * 2);
|
||||
if (!buffer)
|
||||
buffer = xmalloc (buffer_size);
|
||||
else
|
||||
buffer = xrealloc (buffer, buffer_size);
|
||||
|
||||
point = buffer + previous_point_index;
|
||||
}
|
||||
*point++ = c & 0xff;
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
c = getc (stdin);
|
||||
|
||||
/* Catch special case: backslash at end of file */
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
*point++ = c;
|
||||
}
|
||||
}
|
||||
*point = 0;
|
||||
|
||||
if (c != EOF)
|
||||
ungetc (c, stdin);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
yylex ()
|
||||
{
|
||||
int c;
|
||||
char *token;
|
||||
|
||||
|
||||
/* First char determines what token we're looking at */
|
||||
for (;;)
|
||||
{
|
||||
c = getc (stdin);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
return 0;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
/* Ignore whitespace */
|
||||
continue;
|
||||
|
||||
case '#':
|
||||
/* Comments advance to next line */
|
||||
while ((c = getc (stdin)) != '\n' && c != EOF);
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (c != '(' && c != ')' && c != '\\' && c != ',')
|
||||
{
|
||||
ungetc (c, stdin);
|
||||
yylval.string = scan_string ();
|
||||
|
||||
/* Check if string is "define_operator"; if so, return
|
||||
a DEFOP token instead. */
|
||||
if (!strcmp (yylval.string, "define_operator"))
|
||||
{
|
||||
free (yylval.string);
|
||||
yylval.string = 0;
|
||||
return DEFOP;
|
||||
}
|
||||
return STRING;
|
||||
}
|
||||
return c & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/* Utility to generate opcode list from bytecode definition.
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hconfig.h"
|
||||
#include "bi-defs.h"
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct def *d;
|
||||
struct variation *v;
|
||||
int i;
|
||||
|
||||
yyparse();
|
||||
reverse();
|
||||
|
||||
|
||||
printf ("/* This file is automatically generated from bytecode.def,\n");
|
||||
printf ("do not make any changes here. Instead edit bytecode.def. */\n\n");
|
||||
printf ("enum bytecode_opcode\n{");
|
||||
|
||||
i = 0;
|
||||
for (d = defs; d; d = d->next)
|
||||
for (v = d->variations; v; v = v->next)
|
||||
{
|
||||
printf (" %s%s,\n", d->basename, v->name);
|
||||
++i;
|
||||
}
|
||||
|
||||
puts (" LAST_AND_UNUSED_OPCODE\n};");
|
||||
|
||||
if (i > 256)
|
||||
fprintf (stderr, "%s: warning, number of opcodes is %d\n", *argv, i);
|
||||
else
|
||||
fprintf (stderr, "(Number of opcodes is %d)\n", i);
|
||||
|
||||
fflush (stdout);
|
||||
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
|
||||
memory. */
|
||||
char *
|
||||
xmalloc (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *tmp = (char *) malloc (nbytes);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/* Utility to generate opcode name list from bytecode definition file.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hconfig.h"
|
||||
#include "bi-defs.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
struct def *d;
|
||||
struct variation *v;
|
||||
|
||||
yyparse();
|
||||
reverse();
|
||||
|
||||
for (d = defs; d; d = d->next)
|
||||
for (v = d->variations; v; v = v->next)
|
||||
printf("\"%s%s\",\n", d->basename, v->name);
|
||||
|
||||
fflush (stdout);
|
||||
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
|
||||
memory. */
|
||||
char *
|
||||
xmalloc (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *tmp = (char *) malloc (nbytes);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
/* Bytecode definition file parser.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
%{
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hconfig.h"
|
||||
#include "bi-defs.h"
|
||||
|
||||
extern char yytext[];
|
||||
extern int yyleng;
|
||||
|
||||
|
||||
/* Chain of all defs built by the parser. */
|
||||
struct def *defs;
|
||||
int ndefs;
|
||||
|
||||
static struct node *makenode ();
|
||||
static struct variation *makevar ();
|
||||
static struct def *makedef ();
|
||||
|
||||
void yyerror ();
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
char *string;
|
||||
struct def *def;
|
||||
struct variation *variation;
|
||||
struct node *node;
|
||||
}
|
||||
|
||||
%token <string> DEFOP STRING
|
||||
%type <string> opt_string
|
||||
%type <def> defs def
|
||||
%type <variation> variations variation
|
||||
%type <node> list items item
|
||||
|
||||
%%
|
||||
|
||||
top:
|
||||
defs
|
||||
{ defs = $1; }
|
||||
;
|
||||
|
||||
defs:
|
||||
def
|
||||
| defs def
|
||||
{ $2->next = $1; $$ = $2; }
|
||||
;
|
||||
|
||||
def:
|
||||
DEFOP '(' STRING ',' opt_string ',' '(' variations ')' ')'
|
||||
{ $$ = makedef ($3, $5, $8); }
|
||||
;
|
||||
|
||||
variations:
|
||||
variation
|
||||
| variations ',' variation
|
||||
{ $3->next = $1; $$ = $3; }
|
||||
;
|
||||
|
||||
variation:
|
||||
'(' opt_string ')'
|
||||
{ $$ = makevar ($2, (struct node *) NULL, (struct node *) NULL, (struct node *) NULL); }
|
||||
| '(' opt_string ',' list ')'
|
||||
{ $$ = makevar ($2, $4, (struct node *) NULL, (struct node *) NULL); }
|
||||
| '(' opt_string ',' list ',' list ')'
|
||||
{ $$ = makevar ($2, $4, $6, (struct node *) NULL); }
|
||||
| '(' opt_string ',' list ',' list ',' list ')'
|
||||
{ $$ = makevar ($2, $4, $6, $8); }
|
||||
;
|
||||
|
||||
opt_string:
|
||||
/* empty */ { $$ = ""; }
|
||||
| STRING { $$ = $1; }
|
||||
;
|
||||
|
||||
list:
|
||||
'(' items ')'
|
||||
{ $$ = $2; }
|
||||
| /* empty */
|
||||
{ $$ = NULL; }
|
||||
;
|
||||
|
||||
items:
|
||||
item
|
||||
/* Note right recursion. */
|
||||
| item ',' items
|
||||
{ $1->next = $3; $$ = $1; }
|
||||
;
|
||||
|
||||
item:
|
||||
STRING
|
||||
{ $$ = makenode ($1); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
static struct node *
|
||||
makenode (s)
|
||||
char *s;
|
||||
{
|
||||
struct node *n;
|
||||
|
||||
n = (struct node *) malloc (sizeof (struct node));
|
||||
n->text = s;
|
||||
n->next = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
static struct variation *
|
||||
makevar (name, inputs, outputs, literals)
|
||||
char *name;
|
||||
struct node *inputs, *outputs, *literals;
|
||||
{
|
||||
struct variation *v;
|
||||
|
||||
v = (struct variation *) malloc (sizeof (struct variation));
|
||||
v->name = name;
|
||||
v->code = ndefs++;
|
||||
v->inputs = inputs;
|
||||
v->outputs = outputs;
|
||||
v->literals = literals;
|
||||
v->next = NULL;
|
||||
return v;
|
||||
}
|
||||
|
||||
static struct def *
|
||||
makedef (name, template, vars)
|
||||
char *name, *template;
|
||||
struct variation *vars;
|
||||
{
|
||||
struct def *d;
|
||||
|
||||
d = (struct def *) malloc (sizeof (struct def));
|
||||
d->basename = name;
|
||||
d->template = template;
|
||||
d->variations = vars;
|
||||
d->next = NULL;
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror (s)
|
||||
char *s;
|
||||
{
|
||||
fprintf (stderr, "syntax error in input\n");
|
||||
exit (FATAL_EXIT_CODE);
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/* Reverse order of definitions obtained from bytecode definition file.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "hconfig.h"
|
||||
#include "bi-defs.h"
|
||||
|
||||
void
|
||||
reverse()
|
||||
{
|
||||
struct def *dp, *d, *dn;
|
||||
struct variation *vp, *v, *vn;
|
||||
|
||||
dp = defs;
|
||||
if (dp)
|
||||
{
|
||||
vp = dp->variations;
|
||||
if (vp)
|
||||
{
|
||||
for (v = vp->next, vp->next = 0; v; vp = v, v = vn)
|
||||
{
|
||||
vn = v->next;
|
||||
v->next = vp;
|
||||
}
|
||||
dp->variations = vp;
|
||||
}
|
||||
for (d = dp->next, dp->next = 0; d; dp = d, d = dn)
|
||||
{
|
||||
vp = d->variations;
|
||||
if (vp)
|
||||
{
|
||||
for (v = vp->next, vp->next = 0; v; vp = v, v = vn)
|
||||
{
|
||||
vn = v->next;
|
||||
v->next = vp;
|
||||
}
|
||||
d->variations = vp;
|
||||
}
|
||||
dn = d->next;
|
||||
d->next = dp;
|
||||
}
|
||||
defs = dp;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/* Definitions for Bytecode Interpreter.
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define MAXLITERALS 5
|
||||
|
||||
struct arityvec
|
||||
{
|
||||
char ninputs;
|
||||
char noutputs;
|
||||
char nliterals;
|
||||
char literals[MAXLITERALS];
|
||||
};
|
||||
|
||||
struct argtype
|
||||
{
|
||||
int modealign; /* Argument mode:alignment */
|
||||
int size; /* Argument size, in bytes */
|
||||
};
|
||||
|
||||
struct callinfo
|
||||
{
|
||||
int nargs; /* Number of arguments in call */
|
||||
struct argtype retvaltype; /* Type of return value */
|
||||
struct argtype argtypes[1]; /* Argument types */
|
||||
};
|
||||
|
||||
/* Structure describing a bytecode function. If this changes, we also
|
||||
need to change expand_function_end () in bc-trans.c */
|
||||
struct bytecode
|
||||
{
|
||||
int stacksize; /* Depth required of evaluation stack. */
|
||||
int localsize; /* Size in bytes of local variables. */
|
||||
unsigned char *pc0; /* Initial program counter. */
|
||||
void **ptrlit; /* Vector of (relocatable) pointer literals. */
|
||||
struct callinfo *callinfo; /* Vector of procedure call type info. */
|
||||
};
|
||||
|
||||
|
||||
#define INTERP_BPC 8 /* Bits per char */
|
||||
#define INTERP_BPI \
|
||||
(sizeof (int) * INTERP_BPC) /* Bits per int */
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min(L, R) ((L) < (R) ? (L) : (R))
|
||||
#endif
|
||||
|
||||
|
||||
/* bit field operations. */
|
||||
|
||||
/* Low (high) mask: int with low (high) N bits set */
|
||||
|
||||
#define LM(N) ((1 << (N)) - 1)
|
||||
#define HM(N) ((~LM (INTERP_BPI - (N))))
|
||||
|
||||
|
||||
/* Sign-extend SIZE low bits of VALUE to integer (typeof VALUE)
|
||||
Signed bitfields are loaded from memory by the sxloadBI instruction,
|
||||
which first retrieves the bitfield with XFIELD and then sign extends
|
||||
it to an SItype. */
|
||||
|
||||
#define EXTEND(SIZE, VALUE) \
|
||||
({ SUtype value = (SUtype) (VALUE); \
|
||||
(value & (1 << ((SIZE) - 1)) ? value | ~LM (SIZE) : value); })
|
||||
|
||||
|
||||
/* Given OFFSET:SIZE for a bitfield, calculate:
|
||||
|
||||
[1] BYTE_OFFSET = the byte offset of the bit field.
|
||||
[2] BIT_OFFSET = the bit offset of the bit field (less than INTERP_BPC).
|
||||
[3] NBYTES = the number of integral bytes in the bit field.
|
||||
[4] TRAILING_BITS= the number of trailing bits (less than INTERP_BPC).
|
||||
|
||||
|
||||
, , , , , (memory bytes)
|
||||
---------------- (bitfield)
|
||||
| | || | | (divisions)
|
||||
^ ^ ^ ^
|
||||
| | | |__ [4] (bits)
|
||||
| | |_________ [3] (bytes)
|
||||
| |_________________ [2] (bits)
|
||||
|___________________________ [1] (bytes)
|
||||
|
||||
|
||||
The above applies to BYTE_LOW_ENDIAN machines. In BYTE_BIG_ENDIAN machines, the
|
||||
bit numbering is reversed (i.e. bit 0 is the sign bit).
|
||||
|
||||
(All right, so I drew this to keep my tongue in cheek while writing the code below,
|
||||
not because I'm into ASCII art.) */
|
||||
|
||||
|
||||
#define BI_PARAMS(OFFSET, SIZE, BYTE_OFFSET, BIT_OFFSET, NBYTES, TRAILING_BITS) \
|
||||
{ BYTE_OFFSET = (OFFSET) / (INTERP_BPC); \
|
||||
BIT_OFFSET = (OFFSET) % (INTERP_BPC); \
|
||||
NBYTES = ((SIZE) - (INTERP_BPC - (BIT_OFFSET))) / INTERP_BPC; \
|
||||
if ((NBYTES) < 0 || ((NBYTES) > 64)) \
|
||||
NBYTES = 0; \
|
||||
if ((SIZE) + (BIT_OFFSET) <= INTERP_BPC) \
|
||||
TRAILING_BITS = 0; \
|
||||
else \
|
||||
TRAILING_BITS = ((SIZE) - (INTERP_BPC - (BIT_OFFSET))) % INTERP_BPC; }
|
||||
|
||||
|
||||
/* SHIFT_IN_BITS retrieves NBITS bits from SOURCE and shifts into
|
||||
DEST. The bit field starts OFFSET bits into SOURCE.
|
||||
|
||||
OR_IN_BITS copies the NBITS low bits from VALUE into a the bitfield in
|
||||
DEST offset by OFFSET bits. */
|
||||
|
||||
|
||||
#define SHIFT_IN_BITS(DEST, SOURCE, OFFSET, NBITS) \
|
||||
(DEST = ((DEST) << (NBITS)) \
|
||||
| (LM ((NBITS)) \
|
||||
& ((SOURCE) \
|
||||
>> (BYTES_BIG_ENDIAN \
|
||||
? (INTERP_BPC - (OFFSET) - (NBITS)) \
|
||||
: (OFFSET)))))
|
||||
|
||||
#define OR_IN_BITS(DEST, VALUE, OFFSET, NBITS) \
|
||||
(DEST = ((DEST) & ~(LM ((NBITS)) \
|
||||
<< (BIG_ENDIAN \
|
||||
? (INTERP_BPC - (OFFSET) - (NBITS)) \
|
||||
: (OFFSET))) \
|
||||
| (((VALUE) & LM ((NBITS))) \
|
||||
<< (BIG_ENDIAN \
|
||||
? (INTERP_BPC - (OFFSET) - (NBITS)) \
|
||||
: (OFFSET)))))
|
||||
|
||||
/* Procedure call; arguments are a pointer to the function to be called,
|
||||
a pointer to a place to store the return value, a pointer to a vector
|
||||
describing the type of procedure call, and the interpreter's stack pointer,
|
||||
which will point to the first of the arguments at this point. */
|
||||
|
||||
#define CALL(FUNC, CALLDESC, RETVAL, SP) __call(FUNC, CALLDESC, RETVAL, SP)
|
||||
|
||||
|
||||
/* Procedure return; arguments are a pointer to the calldesc for this
|
||||
function, and a pointer to the place where the value to be returned
|
||||
may be found. Generally the MACHARGS above contain a machine dependent
|
||||
cookie that is used to determine where to jump to. */
|
||||
|
||||
#define PROCRET(CALLDESC, RETVAL) return
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
# -*- C -*-
|
||||
# bytecode.def - definitions of bytecodes for the stack machine.
|
||||
|
||||
# The production of the bytecode interpreter and compiler is
|
||||
# heavily automated by using this file creatively.
|
||||
|
||||
# Various elementary data types are understood by the bytecode interpreter.
|
||||
# Q[IU] - quarter word (byte) signed and unsigned integers (char).
|
||||
# H[IU] - half word signed and unsigned integers (short int, maybe int).
|
||||
# S[IU] - single word signed and unsigned integers (maybe int, long int).
|
||||
# D[IU] - double word signed and unsigned integers (long long int).
|
||||
# SF - single precision floating point (float).
|
||||
# DF - double precision floating point (double).
|
||||
# XF - extended precision floating point (long double).
|
||||
# P - pointer type for address arithmetic and other purposes.
|
||||
|
||||
# The bytecode specification consists of a series of define_operator
|
||||
# forms, that are parsed by preprocessors to automatically build
|
||||
# various switch statements.
|
||||
# define_operator(name,
|
||||
# <C prototype code for implementing the operator>,
|
||||
# <list of variations>)
|
||||
# The <C prototype> is self explanatory.
|
||||
# The <list of variations> consists of a (parenthesized list) of
|
||||
# variation items, each of which is in itself a list. A variation
|
||||
# item consists of a name suffix, the types of the input arguments
|
||||
# expected on the stack (shallowest item first) and (optionally) the
|
||||
# types of the output arguments (similarly ordered). Finally, the
|
||||
# types of the literal arguments (if any) may appear.
|
||||
|
||||
# Substitution in the C prototype code is as follows:
|
||||
# Substitution happens only after a dollar sign. To get a literal
|
||||
# dollar sign (why would you ever want one anyway?) use $$.
|
||||
# $R1 means "result 1" $TR1 means "type name of result one"
|
||||
# $S1 means "source 1" and similarly with $TS1.
|
||||
# $L1 means "literal (inline) argument 1" and $TL1 means type thereof.
|
||||
#
|
||||
|
||||
# Notice that the number following $R doesn't affect the push order;
|
||||
# it's used only for clarity and orthogonality, although it's checked
|
||||
# to make sure it doesn't exceed the number of outputs. A $R reference
|
||||
# results in a push, and represents the result lvalue. E.g.
|
||||
|
||||
# $R1 = 2\, $R2 = 17
|
||||
# will expand to:
|
||||
# INTERP_PUSH($TR1) = 2, INTERP_PUSH($TR2) = 17
|
||||
#
|
||||
|
||||
# Opcode 0 should never happen.
|
||||
define_operator(neverneverland, abort\(\), (()))
|
||||
|
||||
# Stack manipulations.
|
||||
define_operator(drop, 0, ((, (SI))))
|
||||
define_operator(duplicate, 0, ((, (SI), (SI, SI))))
|
||||
define_operator(over, 0, ((, (SI), (SI, SI))))
|
||||
|
||||
# Adjust stack pointer
|
||||
|
||||
define_operator(setstack, 0, ((SI,,,(SI))))
|
||||
define_operator(adjstack, 0, ((SI,,,(SI))))
|
||||
|
||||
# Constants, loads, and stores.
|
||||
define_operator(const,
|
||||
$R1 = $L1,
|
||||
((QI,, (QI), (QI)), (HI,, (HI), (HI)),
|
||||
(SI,, (SI), (SI)), (DI,, (DI), (DI)),
|
||||
(SF,, (SF), (SF)), (DF,, (DF), (DF)),
|
||||
(XF,, (XF), (XF)), (P,, (P), (P))))
|
||||
define_operator(load,
|
||||
$R1 = *\($TR1 *\) $S1,
|
||||
((QI, (P), (QI)), (HI, (P), (HI)),
|
||||
(SI, (P), (SI)), (DI, (P), (DI)),
|
||||
(SF, (P), (SF)), (DF, (P), (DF)),
|
||||
(XF, (P), (XF)), (P, (P), (P))))
|
||||
define_operator(store,
|
||||
*\($TS2 *\) $S1 = $S2,
|
||||
((QI, (P, QI)), (HI, (P, HI)),
|
||||
(SI, (P, SI)), (DI, (P, DI)),
|
||||
(SF, (P, SF)), (DF, (P, DF)),
|
||||
(XF, (P, XF)), (P, (P, P)),
|
||||
(BLK, (SI, BLK, BLK))))
|
||||
|
||||
# Clear memory block
|
||||
|
||||
define_operator(clear, $S1 + $S2, ((BLK, (SI, BLK))))
|
||||
|
||||
|
||||
# Advance pointer by SI constant
|
||||
|
||||
define_operator(addconst, $R1 = $S1, ((PSI, (P), (P), (SI))))
|
||||
|
||||
|
||||
# newlocalSI is used for creating variable-sized storage during function
|
||||
# initialization.
|
||||
|
||||
# Create local space, return pointer to block
|
||||
|
||||
define_operator(newlocal, $R1 = $S1, ((SI, (SI), (P))))
|
||||
|
||||
|
||||
# Push the address of a local variable.
|
||||
define_operator(local, $R1 = locals + $L1, ((P,, (P), (SI))))
|
||||
|
||||
# Push the address of an argument variable.
|
||||
define_operator(arg, $R1 = args + $L1, ((P,, (P), (SI))))
|
||||
|
||||
# Arithmetic conversions.
|
||||
define_operator(convert,
|
||||
$R1 = \($TR1\) $S1,
|
||||
(# Signed integral promotions (sign extensions).
|
||||
(QIHI, (QI), (HI)), (HISI, (HI), (SI)), (SIDI, (SI), (DI)),
|
||||
(QISI, (QI), (SI)),
|
||||
# Unsigned integral promotions (zero extensions).
|
||||
(QUHU, (QU), (HU)), (HUSU, (HU), (SU)), (SUDU, (SU), (DU)),
|
||||
(QUSU, (QU), (SU)),
|
||||
# Floating promotions.
|
||||
(SFDF, (SF), (DF)), (DFXF, (DF), (XF)),
|
||||
# Integral truncation.
|
||||
(HIQI, (HI), (QI)), (SIHI, (SI), (HI)), (DISI, (DI), (SI)),
|
||||
(SIQI, (SI), (QI)),
|
||||
# Unsigned truncation.
|
||||
(SUQU, (SU), (QU)),
|
||||
# Floating truncation.
|
||||
(DFSF, (DF), (SF)), (XFDF, (XF), (DF)),
|
||||
# Integral conversions to floating types.
|
||||
(SISF, (SI), (SF)), (SIDF, (SI), (DF)), (SIXF, (SI), (XF)),
|
||||
(SUSF, (SU), (SF)), (SUDF, (SU), (DF)), (SUXF, (SU), (XF)),
|
||||
(DISF, (DI), (SF)), (DIDF, (DI), (DF)), (DIXF, (DI), (XF)),
|
||||
(DUSF, (DU), (SF)), (DUDF, (DU), (DF)), (DUXF, (DU), (XF)),
|
||||
# Floating conversions to integral types.
|
||||
(SFSI, (SF), (SI)), (DFSI, (DF), (SI)), (XFSI, (XF), (SI)),
|
||||
(SFSU, (SF), (SU)), (DFSU, (DF), (SU)), (XFSU, (XF), (SU)),
|
||||
(SFDI, (SF), (DI)), (DFDI, (DF), (DI)), (XFDI, (XF), (DI)),
|
||||
(SFDU, (SF), (DU)), (DFDU, (DF), (DU)), (XFDU, (XF), (DU)),
|
||||
# Pointer/integer conversions.
|
||||
(PSI, (P), (SI)), (SIP, (SI), (P))))
|
||||
|
||||
# Truth value conversion. These are necessary because conversions of, e.g.,
|
||||
# floating types to integers may not function correctly for large values.
|
||||
define_operator(convert,
|
||||
$R1 = !!$S1,
|
||||
((SIT, (SI), (T)), (DIT, (DI), (T)),
|
||||
(SFT, (SF), (T)), (DFT, (DF), (T)),
|
||||
(XFT, (XF), (T)), (PT, (P), (T))))
|
||||
|
||||
# Bit field load/store.
|
||||
|
||||
# Load and zero-extend bitfield
|
||||
|
||||
define_operator(zxload, $R1 = $S1, ((BI, (SU, SU, P), (SU))))
|
||||
|
||||
# Load and sign-extend bitfield
|
||||
|
||||
define_operator(sxload, $R1 = $S1, ((BI, (SU, SU, P), (SI))))
|
||||
|
||||
# Store integer in bitfield
|
||||
|
||||
define_operator(sstore, $R1 = $S1, ((BI, (SU, SU, P, SI))))
|
||||
|
||||
|
||||
# Binary operations.
|
||||
define_operator(add,
|
||||
$R1 = $S1 + $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
|
||||
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
|
||||
(XF, (XF, XF), (XF)),
|
||||
(PSI, (P, SI), (P))))
|
||||
define_operator(sub,
|
||||
$R1 = $S1 - $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
|
||||
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
|
||||
(XF, (XF, XF), (XF)),
|
||||
(PP, (P, P), (SI))))
|
||||
define_operator(mul,
|
||||
$R1 = $S1 * $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
|
||||
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)),
|
||||
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
|
||||
(XF, (XF, XF), (XF))))
|
||||
define_operator(div,
|
||||
$R1 = $S1 / $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
|
||||
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)),
|
||||
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
|
||||
(XF, (XF, XF), (XF))))
|
||||
define_operator(mod,
|
||||
$R1 = $S1 % $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
|
||||
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU))))
|
||||
define_operator(and,
|
||||
$R1 = $S1 & $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
|
||||
define_operator(ior,
|
||||
$R1 = $S1 | $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
|
||||
define_operator(xor,
|
||||
$R1 = $S1 ^ $S2,
|
||||
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
|
||||
define_operator(lshift,
|
||||
$R1 = $S1 << $S2,
|
||||
((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)),
|
||||
(DI, (DI, SI), (DI)), (DU, (DU, SI), (DU))))
|
||||
define_operator(rshift,
|
||||
$R1 = $S1 >> $S2,
|
||||
((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)),
|
||||
(DI, (DI, SI), (DI)), (DU, (DU, SI), (DU))))
|
||||
define_operator(lt,
|
||||
$R1 = $S1 < $S2,
|
||||
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
|
||||
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
define_operator(le,
|
||||
$R1 = $S1 <= $S2,
|
||||
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
|
||||
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
define_operator(ge,
|
||||
$R1 = $S1 >= $S2,
|
||||
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
|
||||
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
define_operator(gt,
|
||||
$R1 = $S1 > $S2,
|
||||
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
|
||||
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
define_operator(eq,
|
||||
$R1 = $S1 == $S2,
|
||||
((SI, (SI, SI), (T)), (DI, (DI, DI), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
define_operator(ne,
|
||||
$R1 = $S1 != $S2,
|
||||
((SI, (SI, SI), (T)), (DI, (DI, DI), (T)),
|
||||
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
|
||||
(XF, (XF, XF), (T)), (P, (P, P), (T))))
|
||||
|
||||
# Unary operations.
|
||||
define_operator(neg,
|
||||
$R1 = -$S1,
|
||||
((SI, (SI), (SI)), (DI, (DI), (DI)),
|
||||
(SF, (SF), (SF)), (DF, (DF), (DF)),
|
||||
(XF, (XF), (XF))))
|
||||
define_operator(not,
|
||||
$R1 = ~$S1,
|
||||
((SI, (SI), (SI)), (DI, (DI), (DI))))
|
||||
define_operator(not,
|
||||
$R1 = !$S1,
|
||||
((T, (SI), (SI))))
|
||||
|
||||
# Increment operations.
|
||||
define_operator(predec,
|
||||
$R1 = *\($TR1 *\) $S1 -= $S2,
|
||||
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
|
||||
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
|
||||
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
|
||||
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
|
||||
(BI, (SU, SU, P, SI), (SI))))
|
||||
|
||||
define_operator(preinc,
|
||||
$R1 = *\($TR1 *\) $S1 += $S2,
|
||||
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
|
||||
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
|
||||
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
|
||||
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
|
||||
(BI, (SU, SU, P, SI), (SI))))
|
||||
|
||||
define_operator(postdec,
|
||||
$R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 -= $S2,
|
||||
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
|
||||
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
|
||||
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
|
||||
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
|
||||
(BI, (SU, SU, P, SI), (SI))))
|
||||
|
||||
define_operator(postinc,
|
||||
$R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 += $S2,
|
||||
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
|
||||
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
|
||||
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
|
||||
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
|
||||
(BI, (SU, SU, P, SI), (SI))))
|
||||
|
||||
# Jumps.
|
||||
define_operator(xjumpif, if \($S1\) pc = code->pc0 + $L1, ((, (T),, (SI))))
|
||||
define_operator(xjumpifnot, if \(! $S1\) pc = code->pc0 + $L1, ((, (T),, (SI))))
|
||||
define_operator(jump, pc = code->pc0 + $L1, ((,,,(SI))))
|
||||
|
||||
# This is for GCC2. It jumps to the address on the stack.
|
||||
define_operator(jump, pc = \(void *\) $S1, ((P,,)))
|
||||
|
||||
# Switches. In order to (eventually) support ranges we provide four different
|
||||
# varieties of switches. Arguments are the switch index from the stack, the
|
||||
# bytecode offset of the switch table, the size of the switch table, and
|
||||
# the default label.
|
||||
define_operator(caseSI, CASESI\($S1\, $L1\, $L2\, $L3\), ((, (SI),, (SI, SI, SI))))
|
||||
define_operator(caseSU, CASESU\($S1\, $L1\, $L2\, $L3\), ((, (SU),, (SI, SI, SI))))
|
||||
define_operator(caseDI, CASEDI\($S1\, $L1\, $L2\, $L3\), ((, (DI),, (SI, SI, SI))))
|
||||
define_operator(caseDU, CASEDU\($S1\, $L1\, $L2\, $L3\), ((, (DU),, (SI, SI, SI))))
|
||||
|
||||
# Procedure call.
|
||||
# Stack arguments are (deepest first):
|
||||
# procedure arguments in reverse order.
|
||||
# pointer to the place to hold the return value.
|
||||
# address of the call description vector.
|
||||
# pointer to the procedure to be called.
|
||||
define_operator(call, CALL\($S1\, $S2\, $S3\, sp\), ((, (P, P, P))))
|
||||
|
||||
# Procedure return.
|
||||
# Pushes on interpreter stack:
|
||||
# value of retptr (pointer to return value storage slot)
|
||||
define_operator(return, $R1 = retptr, ((P,,(P))))
|
||||
|
||||
# Really return.
|
||||
define_operator(ret, return, (()))
|
||||
|
||||
# Print an obnoxious line number.
|
||||
define_operator(linenote, fprintf\(stderr\, "%d\\n"\, $L1\), ((,,,(SI))))
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/* Bytecode definitions for GNU C-compiler.
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
extern int output_bytecode;
|
||||
extern int stack_depth;
|
||||
extern int max_stack_depth;
|
||||
|
||||
/* Emit DI constant according to target machine word ordering */
|
||||
|
||||
#define bc_emit_bytecode_DI_const(CST) \
|
||||
{ int opcode; \
|
||||
opcode = (WORDS_BIG_ENDIAN \
|
||||
? TREE_INT_CST_HIGH (CST) \
|
||||
: TREE_INT_CST_LOW (CST)); \
|
||||
bc_emit_bytecode_const ((char *) &opcode, sizeof opcode); \
|
||||
opcode = (WORDS_BIG_ENDIAN \
|
||||
? TREE_INT_CST_LOW (CST) \
|
||||
: TREE_INT_CST_HIGH (CST)); \
|
||||
bc_emit_bytecode_const ((char *) &opcode, sizeof opcode); \
|
||||
}
|
||||
|
||||
extern void bc_expand_expr ();
|
||||
extern void bc_output_data_constructor ();
|
||||
extern void bc_store_field ();
|
||||
extern void bc_load_bit_field ();
|
||||
extern void bc_store_bit_field ();
|
||||
extern void bc_push_offset_and_size ();
|
||||
extern void bc_init_mode_to_code_map ();
|
||||
|
||||
/* These are just stubs, so the compiler will compile for targets
|
||||
that aren't yet supported by the bytecode generator. */
|
||||
|
||||
#ifndef TARGET_SUPPORTS_BYTECODE
|
||||
|
||||
#define MACHINE_SEG_ALIGN 1
|
||||
#define INT_ALIGN 1
|
||||
#define PTR_ALIGN 1
|
||||
#define NAMES_HAVE_UNDERSCORES
|
||||
#define BC_NOP (0)
|
||||
#define BC_GLOBALIZE_LABEL(FP, NAME) BC_NOP
|
||||
#define BC_OUTPUT_COMMON(FP, NAME, SIZE, ROUNDED) BC_NOP
|
||||
#define BC_OUTPUT_LOCAL(FP, NAME, SIZE, ROUNDED) BC_NOP
|
||||
#define BC_OUTPUT_ALIGN(FP, ALIGN) BC_NOP
|
||||
#define BC_OUTPUT_LABEL(FP, NAME) BC_NOP
|
||||
#define BC_OUTPUT_SKIP(FP, SIZE) BC_NOP
|
||||
#define BC_OUTPUT_LABELREF(FP, NAME) BC_NOP
|
||||
#define BC_OUTPUT_FLOAT(FP, VAL) BC_NOP
|
||||
#define BC_OUTPUT_DOUBLE(FP, VAL) BC_NOP
|
||||
#define BC_OUTPUT_BYTE(FP, VAL) BC_NOP
|
||||
#define BC_OUTPUT_FILE ASM_OUTPUT_FILE
|
||||
#define BC_OUTPUT_ASCII ASM_OUTPUT_ASCII
|
||||
#define BC_OUTPUT_IDENT ASM_OUTPUT_IDENT
|
||||
#define BCXSTR(RTX) ((RTX)->bc_label)
|
||||
#define BC_WRITE_FILE(FP) BC_NOP
|
||||
#define BC_WRITE_SEGSYM(SEGSYM, FP) BC_NOP
|
||||
#define BC_WRITE_RELOC_ENTRY(SEGRELOC, FP, OFFSET) BC_NOP
|
||||
#define BC_START_BYTECODE_LINE(FP) BC_NOP
|
||||
#define BC_WRITE_BYTECODE(SEP, VAL, FP) BC_NOP
|
||||
#define BC_WRITE_RTL(R, FP) BC_NOP
|
||||
#define BC_EMIT_TRAMPOLINE(TRAMPSEG, CALLINFO) BC_NOP
|
||||
#define VALIDATE_STACK BC_NOP
|
||||
|
||||
#endif /* !TARGET_SUPPORTS_BYTECODE */
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/* These should come from genemit */
|
||||
|
||||
/* Use __signed__ in case compiling with -traditional. */
|
||||
|
||||
typedef __signed__ char QItype;
|
||||
typedef unsigned char QUtype;
|
||||
typedef __signed__ short int HItype;
|
||||
typedef unsigned short int HUtype;
|
||||
typedef __signed__ long int SItype;
|
||||
typedef unsigned long int SUtype;
|
||||
typedef __signed__ long long int DItype;
|
||||
typedef unsigned long long int DUtype;
|
||||
typedef float SFtype;
|
||||
typedef double DFtype;
|
||||
typedef long double XFtype;
|
||||
typedef char *Ptype;
|
||||
typedef int Ttype;
|
||||
|
||||
|
||||
typedef union stacktype
|
||||
{
|
||||
QItype QIval;
|
||||
QUtype QUval;
|
||||
HItype HIval;
|
||||
HUtype HUval;
|
||||
SItype SIval;
|
||||
SUtype SUval;
|
||||
DItype DIval;
|
||||
DUtype DUval;
|
||||
SFtype SFval;
|
||||
DFtype DFval;
|
||||
XFtype XFval;
|
||||
Ptype Pval;
|
||||
Ttype Tval;
|
||||
} stacktype;
|
||||
976
contrib/gcc/config.sub
vendored
976
contrib/gcc/config.sub
vendored
|
|
@ -1,976 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script, version 1.1.
|
||||
# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc.
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
# Each package is responsible for reporting which valid configurations
|
||||
# it does not support. The user should be able to distinguish
|
||||
# a failure to support a valid configuration from a meaningless
|
||||
# configuration.
|
||||
|
||||
# The goal of this file is to map all the various variations of a given
|
||||
# machine specification into a single specification in the form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||
# or in some cases, the newer four-part form:
|
||||
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||
# It is wrong to echo any other type of specification.
|
||||
|
||||
if [ x$1 = x ]
|
||||
then
|
||||
echo Configuration name missing. 1>&2
|
||||
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
|
||||
echo "or $0 ALIAS" 1>&2
|
||||
echo where ALIAS is a recognized configuration type. 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# First pass through any local machine types.
|
||||
case $1 in
|
||||
*local*)
|
||||
echo $1
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
linux-gnu*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
then os=`echo $1 | sed 's/.*-/-/'`
|
||||
else os=; fi
|
||||
;;
|
||||
esac
|
||||
|
||||
### Let's recognize common machines as not being operating systems so
|
||||
### that things like config.sub decstation-3100 work. We also
|
||||
### recognize some manufacturers as not being operating systems, so we
|
||||
### can provide default operating systems below.
|
||||
case $os in
|
||||
-sun*os*)
|
||||
# Prevent following clause from handling this invalid input.
|
||||
;;
|
||||
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
|
||||
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
|
||||
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco4)
|
||||
os=-sco3.2v4
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco3.2.[4-9]*)
|
||||
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco3.2v[4-9]*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-isc)
|
||||
os=-isc2.2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-clix*)
|
||||
basic_machine=clipper-intergraph
|
||||
;;
|
||||
-isc*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*)
|
||||
os=-lynxos
|
||||
;;
|
||||
-ptx*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
|
||||
;;
|
||||
-windowsnt*)
|
||||
os=`echo $os | sed -e 's/windowsnt/winnt/'`
|
||||
;;
|
||||
-psos*)
|
||||
os=-psos
|
||||
;;
|
||||
esac
|
||||
|
||||
# Decode aliases for certain CPU-COMPANY combinations.
|
||||
case $basic_machine in
|
||||
# Recognize the basic CPU types without company name.
|
||||
# Some are omitted here because they have special meanings below.
|
||||
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
|
||||
| arme[lb] | pyramid | mn10200 | mn10300 \
|
||||
| tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
|
||||
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
|
||||
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
|
||||
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| sparc | sparclet | sparclite | sparc64 | v850)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
thumb | thumbel)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
i[34567]86)
|
||||
basic_machine=$basic_machine-pc
|
||||
;;
|
||||
# Object if more than one company name word.
|
||||
*-*-*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
# Recognize the basic CPU types with company name.
|
||||
vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
|
||||
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
|
||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
|
||||
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
|
||||
| xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \
|
||||
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
|
||||
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
|
||||
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
|
||||
| sparc64-* | mips64-* | mipsel-* \
|
||||
| mips64el-* | mips64orion-* | mips64orionel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| f301-*)
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
|
||||
basic_machine=m68000-att
|
||||
;;
|
||||
3b*)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
alliant | fx80)
|
||||
basic_machine=fx80-alliant
|
||||
;;
|
||||
altos | altos3068)
|
||||
basic_machine=m68k-altos
|
||||
;;
|
||||
am29k)
|
||||
basic_machine=a29k-none
|
||||
os=-bsd
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
;;
|
||||
amiga | amiga-*)
|
||||
basic_machine=m68k-cbm
|
||||
;;
|
||||
amigaos | amigados)
|
||||
basic_machine=m68k-cbm
|
||||
os=-amigaos
|
||||
;;
|
||||
amigaunix | amix)
|
||||
basic_machine=m68k-cbm
|
||||
os=-sysv4
|
||||
;;
|
||||
apollo68)
|
||||
basic_machine=m68k-apollo
|
||||
os=-sysv
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
;;
|
||||
balance)
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
;;
|
||||
convex-c2)
|
||||
basic_machine=c2-convex
|
||||
os=-bsd
|
||||
;;
|
||||
convex-c32)
|
||||
basic_machine=c32-convex
|
||||
os=-bsd
|
||||
;;
|
||||
convex-c34)
|
||||
basic_machine=c34-convex
|
||||
os=-bsd
|
||||
;;
|
||||
convex-c38)
|
||||
basic_machine=c38-convex
|
||||
os=-bsd
|
||||
;;
|
||||
cray | ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cray2)
|
||||
basic_machine=cray2-cray
|
||||
os=-unicos
|
||||
;;
|
||||
[ctj]90-cray)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
|
||||
basic_machine=mips-dec
|
||||
;;
|
||||
delta | 3300 | motorola-3300 | motorola-delta \
|
||||
| 3300-motorola | delta-motorola)
|
||||
basic_machine=m68k-motorola
|
||||
;;
|
||||
delta88)
|
||||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
dpx20 | dpx20-*)
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
;;
|
||||
dpx2* | dpx2*-bull)
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv3
|
||||
;;
|
||||
ebmon29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-ebmon
|
||||
;;
|
||||
elxsi)
|
||||
basic_machine=elxsi-elxsi
|
||||
os=-bsd
|
||||
;;
|
||||
encore | umax | mmax)
|
||||
basic_machine=ns32k-encore
|
||||
;;
|
||||
fx2800)
|
||||
basic_machine=i860-alliant
|
||||
;;
|
||||
genix)
|
||||
basic_machine=ns32k-ns
|
||||
;;
|
||||
gmicro)
|
||||
basic_machine=tron-gmicro
|
||||
os=-sysv
|
||||
;;
|
||||
h3050r* | hiux*)
|
||||
basic_machine=hppa1.1-hitachi
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
h8300hms)
|
||||
basic_machine=h8300-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
harris)
|
||||
basic_machine=m88k-harris
|
||||
os=-sysv3
|
||||
;;
|
||||
hp300-*)
|
||||
basic_machine=m68k-hp
|
||||
;;
|
||||
hp300bsd)
|
||||
basic_machine=m68k-hp
|
||||
os=-bsd
|
||||
;;
|
||||
hp300hpux)
|
||||
basic_machine=m68k-hp
|
||||
os=-hpux
|
||||
;;
|
||||
hp9k2[0-9][0-9] | hp9k31[0-9])
|
||||
basic_machine=m68000-hp
|
||||
;;
|
||||
hp9k3[2-9][0-9])
|
||||
basic_machine=m68k-hp
|
||||
;;
|
||||
hp9k6[0-9][0-9] | hp6[0-9][0-9] )
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hp9k7[0-79][0-9] | hp7[0-79][0-9] )
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k78[0-9] | hp78[0-9] )
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | \
|
||||
hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893 )
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][13679] | hp8[0-9][13679] )
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][0-9] | hp8[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hppa-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i[34567]86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
;;
|
||||
i[34567]86v4*)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv4
|
||||
;;
|
||||
i[34567]86v)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv
|
||||
;;
|
||||
i[34567]86sol2)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-solaris2
|
||||
;;
|
||||
iris | iris4d)
|
||||
basic_machine=mips-sgi
|
||||
case $os in
|
||||
-irix*)
|
||||
;;
|
||||
*)
|
||||
os=-irix4
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
isi68 | isi)
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
magnum | m3230)
|
||||
basic_machine=mips-mips
|
||||
os=-sysv
|
||||
;;
|
||||
merlin)
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
mipsel*-linux*)
|
||||
basic_machine=mipsel-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips*-linux*)
|
||||
basic_machine=mips-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips3*-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||
;;
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
;;
|
||||
news | news700 | news800 | news900)
|
||||
basic_machine=m68k-sony
|
||||
os=-newsos
|
||||
;;
|
||||
news1000)
|
||||
basic_machine=m68030-sony
|
||||
os=-newsos
|
||||
;;
|
||||
news-3600 | risc-news)
|
||||
basic_machine=mips-sony
|
||||
os=-newsos
|
||||
;;
|
||||
next | m*-next )
|
||||
basic_machine=m68k-next
|
||||
case $os in
|
||||
-nextstep* )
|
||||
;;
|
||||
-ns2*)
|
||||
os=-nextstep2
|
||||
;;
|
||||
*)
|
||||
os=-nextstep3
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
nh3000)
|
||||
basic_machine=m68k-harris
|
||||
os=-cxux
|
||||
;;
|
||||
nh[45]000)
|
||||
basic_machine=m88k-harris
|
||||
os=-cxux
|
||||
;;
|
||||
nindy960)
|
||||
basic_machine=i960-intel
|
||||
os=-nindy
|
||||
;;
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
pa-hitachi)
|
||||
basic_machine=hppa1.1-hitachi
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
paragon)
|
||||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
pbb)
|
||||
basic_machine=m68k-tti
|
||||
;;
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pentium | p5 | k5 | nexen)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6 | k6 | 6x86)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentiumii | pentium2)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | nexen-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | k6-* | 6x86-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
power) basic_machine=rs6000-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ps2)
|
||||
basic_machine=i386-ibm
|
||||
;;
|
||||
rm[46]00)
|
||||
basic_machine=mips-siemens
|
||||
;;
|
||||
rtpc | rtpc-*)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
sh)
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sps7)
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv2
|
||||
;;
|
||||
spur)
|
||||
basic_machine=spur-unknown
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
sun2os3)
|
||||
basic_machine=m68000-sun
|
||||
os=-sunos3
|
||||
;;
|
||||
sun2os4)
|
||||
basic_machine=m68000-sun
|
||||
os=-sunos4
|
||||
;;
|
||||
sun3os3)
|
||||
basic_machine=m68k-sun
|
||||
os=-sunos3
|
||||
;;
|
||||
sun3os4)
|
||||
basic_machine=m68k-sun
|
||||
os=-sunos4
|
||||
;;
|
||||
sun4os3)
|
||||
basic_machine=sparc-sun
|
||||
os=-sunos3
|
||||
;;
|
||||
sun4os4)
|
||||
basic_machine=sparc-sun
|
||||
os=-sunos4
|
||||
;;
|
||||
sun4sol2)
|
||||
basic_machine=sparc-sun
|
||||
os=-solaris2
|
||||
;;
|
||||
sun3 | sun3-*)
|
||||
basic_machine=m68k-sun
|
||||
;;
|
||||
sun4)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
sun386 | sun386i | roadrunner)
|
||||
basic_machine=i386-sun
|
||||
;;
|
||||
symmetry)
|
||||
basic_machine=i386-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
tx39el)
|
||||
basic_machine=mipstx39el-unknown
|
||||
;;
|
||||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
udi29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
ultra3)
|
||||
basic_machine=a29k-nyu
|
||||
os=-sym1
|
||||
;;
|
||||
vaxv)
|
||||
basic_machine=vax-dec
|
||||
os=-sysv
|
||||
;;
|
||||
vms)
|
||||
basic_machine=vax-dec
|
||||
os=-vms
|
||||
;;
|
||||
vpp*|vx|vx-*)
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
vxworks960)
|
||||
basic_machine=i960-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
vxworks68)
|
||||
basic_machine=m68k-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
vxworks29k)
|
||||
basic_machine=a29k-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
xmp)
|
||||
basic_machine=xmp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
;;
|
||||
|
||||
# Here we handle the default manufacturer of certain CPU types. It is in
|
||||
# some cases the only manufacturer, in others, it is the most popular.
|
||||
mips)
|
||||
if [ x$os = x-linux-gnu ]; then
|
||||
basic_machine=mips-unknown
|
||||
else
|
||||
basic_machine=mips-mips
|
||||
fi
|
||||
;;
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
vax)
|
||||
basic_machine=vax-dec
|
||||
;;
|
||||
pdp11)
|
||||
basic_machine=pdp11-dec
|
||||
;;
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sparc)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
basic_machine=cydra-cydrome
|
||||
;;
|
||||
orion)
|
||||
basic_machine=orion-highlevel
|
||||
;;
|
||||
orion105)
|
||||
basic_machine=clipper-highlevel
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Here we canonicalize certain aliases for manufacturers.
|
||||
case $basic_machine in
|
||||
*-digital*)
|
||||
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
|
||||
;;
|
||||
*-commodore*)
|
||||
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# Decode manufacturer-specific aliases for certain operating systems.
|
||||
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
-solaris)
|
||||
os=-solaris2
|
||||
;;
|
||||
-svr4*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-unixware*)
|
||||
os=-sysv4.2uw
|
||||
;;
|
||||
-gnu/linux*)
|
||||
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
|
||||
;;
|
||||
# First accept the basic system types.
|
||||
# The portable systems comes first.
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* )
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
-sunos5*)
|
||||
os=`echo $os | sed -e 's|sunos5|solaris2|'`
|
||||
;;
|
||||
-sunos6*)
|
||||
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
||||
;;
|
||||
-osfrose*)
|
||||
os=-osfrose
|
||||
;;
|
||||
-osf*)
|
||||
os=-osf
|
||||
;;
|
||||
-utek*)
|
||||
os=-bsd
|
||||
;;
|
||||
-dynix*)
|
||||
os=-bsd
|
||||
;;
|
||||
-acis*)
|
||||
os=-aos
|
||||
;;
|
||||
-ctix* | -uts*)
|
||||
os=-sysv
|
||||
;;
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
;;
|
||||
# Preserve the version number of sinix5.
|
||||
-sinix5.*)
|
||||
os=`echo $os | sed -e 's|sinix|sysv|'`
|
||||
;;
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-triton*)
|
||||
os=-sysv3
|
||||
;;
|
||||
-oss*)
|
||||
os=-sysv3
|
||||
;;
|
||||
-svr4)
|
||||
os=-sysv4
|
||||
;;
|
||||
-svr3)
|
||||
os=-sysv3
|
||||
;;
|
||||
-sysvr4)
|
||||
os=-sysv4
|
||||
;;
|
||||
# This must come after -sysvr4.
|
||||
-sysv*)
|
||||
;;
|
||||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
# Get rid of the `-' at the beginning of $os.
|
||||
os=`echo $os | sed 's/[^-]*-//'`
|
||||
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
|
||||
# Here we handle the default operating systems that come with various machines.
|
||||
# The value should be what the vendor currently ships out the door with their
|
||||
# machine or put another way, the most popular os provided with the machine.
|
||||
|
||||
# Note that if you're going to try to match "-MANUFACTURER" here (say,
|
||||
# "-sun"), then you have to tell the case statement up towards the top
|
||||
# that MANUFACTURER isn't an operating system. Otherwise, code above
|
||||
# will signal an error saying that MANUFACTURER isn't an operating
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
pdp11-*)
|
||||
os=-none
|
||||
;;
|
||||
*-dec | vax-*)
|
||||
os=-ultrix4.2
|
||||
;;
|
||||
m68*-apollo)
|
||||
os=-domain
|
||||
;;
|
||||
i386-sun)
|
||||
os=-sunos4.0.2
|
||||
;;
|
||||
m68000-sun)
|
||||
os=-sunos3
|
||||
# This also exists in the configure program, but was not the
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
*-tti) # must be before sparc entry or we get the wrong os.
|
||||
os=-sysv3
|
||||
;;
|
||||
sparc-* | *-sun)
|
||||
os=-sunos4.1.1
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-hp)
|
||||
os=-hpux
|
||||
;;
|
||||
*-hitachi)
|
||||
os=-hiux
|
||||
;;
|
||||
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
|
||||
os=-sysv
|
||||
;;
|
||||
*-cbm)
|
||||
os=-amigaos
|
||||
;;
|
||||
*-dg)
|
||||
os=-dgux
|
||||
;;
|
||||
*-dolphin)
|
||||
os=-sysv3
|
||||
;;
|
||||
m68k-ccur)
|
||||
os=-rtu
|
||||
;;
|
||||
m88k-omron*)
|
||||
os=-luna
|
||||
;;
|
||||
*-next )
|
||||
os=-nextstep
|
||||
;;
|
||||
*-sequent)
|
||||
os=-ptx
|
||||
;;
|
||||
*-crds)
|
||||
os=-unos
|
||||
;;
|
||||
*-ns)
|
||||
os=-genix
|
||||
;;
|
||||
i370-*)
|
||||
os=-mvs
|
||||
;;
|
||||
*-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
*-gould)
|
||||
os=-sysv
|
||||
;;
|
||||
*-highlevel)
|
||||
os=-bsd
|
||||
;;
|
||||
*-encore)
|
||||
os=-bsd
|
||||
;;
|
||||
*-sgi)
|
||||
os=-irix
|
||||
;;
|
||||
*-siemens)
|
||||
os=-sysv4
|
||||
;;
|
||||
*-masscomp)
|
||||
os=-rtu
|
||||
;;
|
||||
f301-fujitsu)
|
||||
os=-uxpv
|
||||
;;
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*)
|
||||
os=-none
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Here we handle the case where we know the os, and the CPU type, but not the
|
||||
# manufacturer. We pick the logical manufacturer.
|
||||
vendor=unknown
|
||||
case $basic_machine in
|
||||
*-unknown)
|
||||
case $os in
|
||||
-riscix*)
|
||||
vendor=acorn
|
||||
;;
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-hpux*)
|
||||
vendor=hp
|
||||
;;
|
||||
-hiux*)
|
||||
vendor=hitachi
|
||||
;;
|
||||
-unos*)
|
||||
vendor=crds
|
||||
;;
|
||||
-dgux*)
|
||||
vendor=dg
|
||||
;;
|
||||
-luna*)
|
||||
vendor=omron
|
||||
;;
|
||||
-genix*)
|
||||
vendor=ns
|
||||
;;
|
||||
-mvs*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-vxsim* | -vxworks*)
|
||||
vendor=wrs
|
||||
;;
|
||||
-aux*)
|
||||
vendor=apple
|
||||
;;
|
||||
-beos*)
|
||||
vendor=be
|
||||
;;
|
||||
esac
|
||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/* Configuration for an i386 running MS-DOS with djgpp/go32. */
|
||||
|
||||
#include "dbxcoff.h"
|
||||
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
|
||||
#define YES_UNDERSCORES
|
||||
|
||||
#include "i386/gas.h"
|
||||
|
||||
#ifdef CPP_PREDEFINES
|
||||
#undef CPP_PREDEFINES
|
||||
#endif
|
||||
#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DMSDOS \
|
||||
-Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_ctor, in_dtor
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CTOR_SECTION_FUNCTION \
|
||||
DTOR_SECTION_FUNCTION
|
||||
|
||||
#define CTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
ctor_section () \
|
||||
{ \
|
||||
if (in_section != in_ctor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .ctor\n"); \
|
||||
in_section = in_ctor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
dtor_section () \
|
||||
{ \
|
||||
if (in_section != in_dtor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .dtor\n"); \
|
||||
in_section = in_dtor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Allow (eg) __attribute__((section "locked")) to work */
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC)\
|
||||
do { \
|
||||
fprintf (FILE, "\t.section %s\n", NAME); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Output at beginning of assembler file. */
|
||||
/* The .file command should always begin the output. */
|
||||
/* Use the main_input_filename instead of dump_base_name */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { \
|
||||
output_file_directive (FILE, main_input_filename); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
if ((LOG) != 0) fprintf ((FILE), "\t.p2align %d\n", LOG)
|
||||
|
||||
/* djgpp has atexit (). */
|
||||
#undef HAVE_ATEXIT
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
/* djgpp automatically calls its own version of __main, so don't define one
|
||||
in libgcc, nor call one in main(). */
|
||||
#define HAS_INIT_SECTION
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/* Definitions for Intel 386 running Interactive Unix System V,
|
||||
producing stabs-in-coff output (using a slightly modified gas).
|
||||
Specifically, this is for recent versions that support POSIX;
|
||||
for version 2.0.2, use configuration option i386-sysv instead. */
|
||||
|
||||
/* Underscores are not used on ISC systems (probably not on any COFF
|
||||
system), despite the comments in i386/gas.h. If this is not defined,
|
||||
enquire (for example) will fail to link. --karl@cs.umb.edu */
|
||||
#define NO_UNDERSCORES
|
||||
|
||||
/* Mostly like other gas-using systems. */
|
||||
#include "i386/gas.h"
|
||||
|
||||
/* But with ISC-specific additions. */
|
||||
#include "i386/isc.h"
|
||||
|
||||
/* We do not want to output SDB debugging information. */
|
||||
|
||||
#undef SDB_DEBUGGING_INFO
|
||||
|
||||
/* We want to output DBX debugging information. */
|
||||
|
||||
#define DBX_DEBUGGING_INFO
|
||||
|
||||
|
||||
/* The function `dbxout_init' in dbxout.c omits the first character of
|
||||
`ltext_label_name' when outputting the main source directory and main
|
||||
source filename. I don't understand why, but rather than making a
|
||||
system-independent change there, I override dbxout.c's defaults.
|
||||
Perhaps it would be better to use ".Ltext0" instead of
|
||||
`ltext_label_name', but we've already generated the label, so we just
|
||||
use it here. --karl@cs.umb.edu */
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_DIRECTORY(asmfile, cwd) \
|
||||
do { fprintf (asmfile, "%s ", ASM_STABS_OP); \
|
||||
output_quoted_string (asmfile, cwd); \
|
||||
fprintf (asmfile, ",%d,0,0,%s\n", N_SO, ltext_label_name); \
|
||||
} while (0)
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(asmfile, input_file_name) \
|
||||
fprintf (asmfile, "%s ", ASM_STABS_OP); \
|
||||
output_quoted_string (input_file_name); \
|
||||
fprintf (asmfile, ",%d,0,0,%s\n", N_SO, ltext_label_name); \
|
||||
text_section (); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0)
|
||||
|
||||
|
||||
/* Because we don't include `svr3.h', we haven't yet defined SIZE_TYPE
|
||||
and PTRDIFF_TYPE. ISC's definitions don't match GCC's defaults, so: */
|
||||
|
||||
#undef SIZE_TYPE
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
#undef PTRDIFF_TYPE
|
||||
#define PTRDIFF_TYPE "int"
|
||||
|
||||
|
||||
/* But we can't use crtbegin.o and crtend.o, because gas 1.38.1 doesn't
|
||||
grok .section. The definitions here are otherwise identical to those
|
||||
in i386/isc.h. */
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shlib:%{posix:%{pg:mcrtp1.o%s}%{!pg:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}}\
|
||||
%{!posix:%{pg:mcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}\
|
||||
%{p:-L/lib/libp} %{pg:-L/lib/libp}}}\
|
||||
%{shlib:%{posix:crtp1.o%s}%{!posix:crt1.o%s}}"
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "crtn.o%s"
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* next.c: Functions for NeXT as target machine for GNU C compiler. */
|
||||
|
||||
/* Note that the include below means that we can't debug routines in
|
||||
i386.c when running on a COFF system. */
|
||||
|
||||
#include "i386/i386.c"
|
||||
#include "nextstep.c"
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* Target definitions for GNU compiler for Intel 80386 running System V.4
|
||||
with gas and gdb. */
|
||||
|
||||
/* Use stabs instead of DWARF debug format. */
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
|
||||
#include "i386/sysv4.h"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
# The one that comes with the system is POSIX-compliant.
|
||||
LIMITS_H =
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
/* Configuration for GCC for Intel i386 running NetBSD as host. */
|
||||
|
||||
#include <i386/xm-i386.h>
|
||||
#include <xm-netbsd.h>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Don't run fixproto
|
||||
STMP_FIXPROTO =
|
||||
|
||||
# We don't need GCC's own include files.
|
||||
USER_H =
|
||||
INSTALL_ASSERT_H =
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/* Configuration for GNU C-compiler for hosts running NetBSD.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file defines machine-independent things specific to a host
|
||||
running NetBSD. This file should not be specified as $xm_file itself;
|
||||
instead $xm_file should be CPU/xm-netbsd.h, which should include both
|
||||
CPU/xm-CPU.h and this file xm-netbsd.h. */
|
||||
|
||||
#define HAVE_VPRINTF
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/* Variables and structures for overloading rules.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The following structure is used when comparing various alternatives
|
||||
for overloading. The unsigned quantity `strikes.i' is used
|
||||
for fast comparison of two possibilities. This number is an
|
||||
aggregate of four constituents:
|
||||
|
||||
EVIL: if this is non-zero, then the candidate should not be considered
|
||||
ELLIPSIS: if this is non-zero, then some actual argument has been matched
|
||||
against an ellipsis
|
||||
USER: if this is non-zero, then a user-defined type conversion is needed
|
||||
B_OR_D: if this is non-zero, then use a base pointer instead of the
|
||||
type of the pointer we started with.
|
||||
EASY: if this is non-zero, then we have a builtin conversion
|
||||
(such as int to long, int to float, etc) to do.
|
||||
|
||||
If two candidates require user-defined type conversions, and the
|
||||
type conversions are not identical, then an ambiguity error
|
||||
is reported.
|
||||
|
||||
If two candidates agree on user-defined type conversions,
|
||||
and one uses pointers of strictly higher type (derived where
|
||||
another uses base), then that alternative is silently chosen.
|
||||
|
||||
Note that this technique really only works for 255 arguments. Perhaps
|
||||
this is not enough. */
|
||||
|
||||
/* These macros and harshness_code are used by the NEW METHOD. */
|
||||
#define EVIL_CODE (1<<7)
|
||||
#define CONST_CODE (1<<6)
|
||||
#define ELLIPSIS_CODE (1<<5)
|
||||
#define USER_CODE (1<<4)
|
||||
#define STD_CODE (1<<3)
|
||||
#define PROMO_CODE (1<<2)
|
||||
#define QUAL_CODE (1<<1)
|
||||
#define TRIVIAL_CODE (1<<0)
|
||||
|
||||
struct harshness_code
|
||||
{
|
||||
/* What kind of conversion is involved. */
|
||||
unsigned short code;
|
||||
|
||||
/* The inheritance distance. */
|
||||
short distance;
|
||||
|
||||
/* For a PROMO_CODE, Any special penalties involved in integral conversions.
|
||||
This exists because $4.1 of the ARM states that something like
|
||||
`short unsigned int' should promote to `int', not `unsigned int'.
|
||||
If, for example, it tries to match two fns, f(int) and f(unsigned),
|
||||
f(int) should be a better match than f(unsigned) by this rule. Without
|
||||
this extra metric, they both only appear as "integral promotions", which
|
||||
will lead to an ambiguity.
|
||||
For a TRIVIAL_CODE, This is also used by build_overload_call_real and
|
||||
convert_harshness to keep track of other information we need. */
|
||||
unsigned short int_penalty;
|
||||
};
|
||||
|
||||
struct candidate
|
||||
{
|
||||
struct harshness_code h; /* Used for single-argument conversions. */
|
||||
|
||||
int h_len; /* The length of the harshness vector. */
|
||||
|
||||
tree function; /* A FUNCTION_DECL */
|
||||
tree basetypes; /* The path to function. */
|
||||
tree arg; /* first parm to function. */
|
||||
|
||||
/* Indexed by argument number, encodes evil, user, d_to_b, and easy
|
||||
strikes for that argument. At end of array, we store the index+1
|
||||
of where we started using default parameters, or 0 if there are
|
||||
none. */
|
||||
struct harshness_code *harshness;
|
||||
|
||||
union
|
||||
{
|
||||
tree field; /* If no evil strikes, the FUNCTION_DECL of
|
||||
the function (if a member function). */
|
||||
int bad_arg; /* the index of the first bad argument:
|
||||
0 if no bad arguments
|
||||
> 0 is first bad argument
|
||||
-1 if extra actual arguments
|
||||
-2 if too few actual arguments.
|
||||
-3 if const/non const method mismatch.
|
||||
-4 if type unification failed.
|
||||
-5 if contravariance violation. */
|
||||
} u;
|
||||
};
|
||||
int rank_for_overload ();
|
||||
|
||||
/* Variables shared between class.c and call.c. */
|
||||
|
||||
extern int n_vtables;
|
||||
extern int n_vtable_entries;
|
||||
extern int n_vtable_searches;
|
||||
extern int n_vtable_elems;
|
||||
extern int n_convert_harshness;
|
||||
extern int n_compute_conversion_costs;
|
||||
extern int n_build_method_call;
|
||||
extern int n_inner_fields_searched;
|
||||
|
|
@ -1,928 +0,0 @@
|
|||
/* Interface to LUCID Cadillac system for GNU compiler.
|
||||
Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
#include <stdio.h>
|
||||
#include "cp-tree.h"
|
||||
#include "obstack.h"
|
||||
|
||||
#ifdef CADILLAC
|
||||
#include <compilerreq.h>
|
||||
#include <compilerconn.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
|
||||
void init_cadillac ();
|
||||
|
||||
extern char *input_filename;
|
||||
extern int lineno;
|
||||
|
||||
/* Put random information we might want to get back from
|
||||
Cadillac here. */
|
||||
typedef struct
|
||||
{
|
||||
/* The connection to the Cadillac kernel. */
|
||||
Connection *conn;
|
||||
|
||||
/* Input and output file descriptors for Cadillac. */
|
||||
short fd_input, fd_output;
|
||||
|
||||
/* #include nesting of current file. */
|
||||
short depth;
|
||||
|
||||
/* State variables for the connection. */
|
||||
char messages;
|
||||
char conversion;
|
||||
char emission;
|
||||
char process_until;
|
||||
|
||||
/* #if level of current file. */
|
||||
int iflevel;
|
||||
|
||||
/* Line number that starts current source file. */
|
||||
int lineno;
|
||||
|
||||
/* Name of current file. */
|
||||
char *filename;
|
||||
|
||||
/* Where to stop processing (if process_until is set). */
|
||||
char *end_filename;
|
||||
int end_position;
|
||||
|
||||
} cadillac_struct;
|
||||
static cadillac_struct cadillacObj;
|
||||
|
||||
/* Nonzero if in the process of exiting. */
|
||||
static int exiting;
|
||||
|
||||
void cadillac_note_source ();
|
||||
static void CWriteLanguageDecl ();
|
||||
static void CWriteLanguageType ();
|
||||
static void CWriteTopLevel ();
|
||||
static void cadillac_note_filepos ();
|
||||
static void cadillac_process_request (), cadillac_process_requests ();
|
||||
static void cadillac_switch_source ();
|
||||
static void exit_cadillac ();
|
||||
|
||||
/* Blocking test. */
|
||||
static int
|
||||
readable_p (fd)
|
||||
int fd;
|
||||
{
|
||||
fd_set f;
|
||||
|
||||
FD_ZERO (&f);
|
||||
FD_SET (fd, &f);
|
||||
|
||||
return select (32, &f, NULL, NULL, 0) == 1;
|
||||
}
|
||||
|
||||
static CObjectType *tree_to_cadillac_map;
|
||||
struct obstack cadillac_obstack;
|
||||
|
||||
|
||||
#include "stack.h"
|
||||
|
||||
struct context_level
|
||||
{
|
||||
struct stack_level base;
|
||||
|
||||
tree context;
|
||||
};
|
||||
|
||||
/* Stack for maintaining contexts (in case functions or types are nested).
|
||||
When defining a struct type, the `context' field is the RECORD_TYPE.
|
||||
When defining a function, the `context' field is the FUNCTION_DECL. */
|
||||
|
||||
static struct context_level *context_stack;
|
||||
|
||||
static struct context_level *
|
||||
push_context_level (stack, obstack)
|
||||
struct stack_level *stack;
|
||||
struct obstack *obstack;
|
||||
{
|
||||
struct context_level tem;
|
||||
|
||||
tem.base.prev = stack;
|
||||
return (struct context_level *)push_stack_level (obstack, &tem, sizeof (tem));
|
||||
}
|
||||
|
||||
/* Discard a level of search allocation. */
|
||||
|
||||
static struct context_level *
|
||||
pop_context_level (stack)
|
||||
struct context_level *stack;
|
||||
{
|
||||
stack = (struct context_level *)pop_stack_level (stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
void
|
||||
init_cadillac ()
|
||||
{
|
||||
extern FILE *finput;
|
||||
extern int errno;
|
||||
CCompilerMessage* req;
|
||||
cadillac_struct *cp = &cadillacObj;
|
||||
int i;
|
||||
|
||||
if (! flag_cadillac)
|
||||
return;
|
||||
|
||||
tree_to_cadillac_map = (CObjectType*) xmalloc (sizeof (CObjectType) * LAST_CPLUS_TREE_CODE);
|
||||
for (i = 0; i < LAST_CPLUS_TREE_CODE; i++)
|
||||
tree_to_cadillac_map[i] = MiscOType;
|
||||
tree_to_cadillac_map[RECORD_TYPE] = StructOType;
|
||||
tree_to_cadillac_map[UNION_TYPE] = UnionOType;
|
||||
tree_to_cadillac_map[ENUMERAL_TYPE] = EnumTypeOType;
|
||||
tree_to_cadillac_map[TYPE_DECL] = TypedefOType;
|
||||
tree_to_cadillac_map[VAR_DECL] = VariableOType;
|
||||
tree_to_cadillac_map[CONST_DECL] = EnumConstantOType;
|
||||
tree_to_cadillac_map[FUNCTION_DECL] = FunctionOType;
|
||||
tree_to_cadillac_map[FIELD_DECL] = FieldOType;
|
||||
|
||||
#ifdef sun
|
||||
on_exit (&exit_cadillac, 0);
|
||||
#endif
|
||||
|
||||
gcc_obstack_init (&cadillac_obstack);
|
||||
|
||||
/* Yow! This is the way Cadillac was designed to deal with
|
||||
Oregon C++ compiler! */
|
||||
cp->fd_input = flag_cadillac;
|
||||
cp->fd_output = flag_cadillac;
|
||||
|
||||
/* Start in "turned-on" state. */
|
||||
cp->messages = 1;
|
||||
cp->conversion = 1;
|
||||
cp->emission = 1;
|
||||
|
||||
/* Establish a connection with Cadillac here. */
|
||||
cp->conn = NewConnection (cp, cp->fd_input, cp->fd_output);
|
||||
|
||||
CWriteHeader (cp->conn, WaitingMType, 0);
|
||||
CWriteRequestBuffer (cp->conn);
|
||||
|
||||
if (!readable_p (cp->fd_input))
|
||||
;
|
||||
|
||||
req = CReadCompilerMessage (cp->conn);
|
||||
|
||||
if (!req)
|
||||
switch (errno)
|
||||
{
|
||||
case EWOULDBLOCK:
|
||||
sleep (5);
|
||||
return;
|
||||
|
||||
case 0:
|
||||
fatal ("init_cadillac: EOF on connection to kernel, exiting\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
perror ("Editor to kernel connection");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cadillac_process_requests (conn)
|
||||
Connection *conn;
|
||||
{
|
||||
CCompilerMessage *req;
|
||||
while (req = (CCompilerMessage*) CPeekNextRequest (conn))
|
||||
{
|
||||
req = CReadCompilerMessage (conn);
|
||||
cadillac_process_request (&cadillacObj, req);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cadillac_process_request (cp, req)
|
||||
cadillac_struct *cp;
|
||||
CCompilerMessage *req;
|
||||
{
|
||||
if (! req)
|
||||
return;
|
||||
|
||||
switch (req->reqType)
|
||||
{
|
||||
case ProcessUntilMType:
|
||||
if (cp->process_until)
|
||||
my_friendly_abort (23);
|
||||
cp->process_until = 1;
|
||||
/* This is not really right. */
|
||||
cp->end_position = ((CCompilerCommand*)req)->processuntil.position;
|
||||
#if 0
|
||||
cp->end_filename = req->processuntil.filename;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CommandMType:
|
||||
switch (req->header.data)
|
||||
{
|
||||
case MessagesOnCType:
|
||||
cp->messages = 1;
|
||||
break;
|
||||
case MessagesOffCType:
|
||||
cp->messages = 0;
|
||||
break;
|
||||
case ConversionOnCType:
|
||||
cp->conversion = 1;
|
||||
break;
|
||||
case ConversionOffCType:
|
||||
cp->conversion = 0;
|
||||
break;
|
||||
case EmissionOnCType:
|
||||
cp->emission = 1;
|
||||
break;
|
||||
case EmissionOffCType:
|
||||
cp->emission = 0;
|
||||
break;
|
||||
|
||||
case FinishAnalysisCType:
|
||||
return;
|
||||
|
||||
case PuntAnalysisCType:
|
||||
case ContinueAnalysisCType:
|
||||
case GotoFileposCType:
|
||||
case OpenSucceededCType:
|
||||
case OpenFailedCType:
|
||||
fprintf (stderr, "request type %d not implemented\n", req->reqType);
|
||||
return;
|
||||
|
||||
case DieCType:
|
||||
if (! exiting)
|
||||
my_friendly_abort (24);
|
||||
return;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal ("unknown request type %d", req->reqType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_start ()
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
CCompilerMessage *req;
|
||||
|
||||
/* Let Cadillac know that we start in C++ language scope. */
|
||||
CWriteHeader (conn, ForeignLinkageMType, LinkCPlus);
|
||||
CWriteLength (conn);
|
||||
CWriteRequestBuffer (conn);
|
||||
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
cadillac_printf (msg, name)
|
||||
{
|
||||
if (cadillacObj.messages)
|
||||
printf ("[%s,%4d] %s `%s'\n", input_filename, lineno, msg, name);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_start_decl (decl)
|
||||
tree decl;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
CObjectType object_type = tree_to_cadillac_map [TREE_CODE (decl)];
|
||||
|
||||
if (context_stack)
|
||||
switch (TREE_CODE (context_stack->context))
|
||||
{
|
||||
case FUNCTION_DECL:
|
||||
/* Currently, cadillac only implements top-level forms. */
|
||||
return;
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
cadillac_printf ("start class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
|
||||
break;
|
||||
default:
|
||||
my_friendly_abort (25);
|
||||
}
|
||||
else
|
||||
{
|
||||
cadillac_printf ("start top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
||||
CWriteTopLevel (conn, StartMType);
|
||||
}
|
||||
|
||||
CWriteLanguageDecl (conn, decl, tree_to_cadillac_map[TREE_CODE (decl)]);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_decl (decl)
|
||||
tree decl;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
if (context_stack)
|
||||
switch (TREE_CODE (context_stack->context))
|
||||
{
|
||||
case FUNCTION_DECL:
|
||||
return;
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
cadillac_printf ("end class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
break;
|
||||
default:
|
||||
my_friendly_abort (26);
|
||||
}
|
||||
else
|
||||
{
|
||||
cadillac_printf ("end top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
}
|
||||
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_start_function (fndecl)
|
||||
tree fndecl;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
if (context_stack)
|
||||
/* nested functions not yet handled. */
|
||||
my_friendly_abort (27);
|
||||
|
||||
cadillac_printf ("start top-level function", lang_printable_name (fndecl));
|
||||
context_stack = push_context_level (context_stack, &cadillac_obstack);
|
||||
context_stack->context = fndecl;
|
||||
|
||||
CWriteTopLevel (conn, StartMType);
|
||||
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 202);
|
||||
CWriteLanguageDecl (conn, fndecl,
|
||||
(TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
|
||||
? MemberFnOType : FunctionOType));
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_function (fndecl)
|
||||
tree fndecl;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
cadillac_printf ("end top-level function", lang_printable_name (fndecl));
|
||||
context_stack = pop_context_level (context_stack);
|
||||
|
||||
if (context_stack)
|
||||
/* nested functions not yet implemented. */
|
||||
my_friendly_abort (28);
|
||||
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_anon_union (decl)
|
||||
tree decl;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
if (! global_bindings_p ())
|
||||
return;
|
||||
cadillac_printf ("finish top-level anon union", "");
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_start_enum (type)
|
||||
tree type;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
tree name = TYPE_NAME (type);
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
|
||||
if (context_stack)
|
||||
switch (TREE_CODE (context_stack->context))
|
||||
{
|
||||
case FUNCTION_DECL:
|
||||
return;
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
break;
|
||||
default:
|
||||
my_friendly_abort (29);
|
||||
}
|
||||
else
|
||||
{
|
||||
cadillac_printf ("start top-level enum", IDENTIFIER_POINTER (name));
|
||||
CWriteTopLevel (conn, StartMType);
|
||||
}
|
||||
|
||||
CWriteLanguageType (conn, type, tree_to_cadillac_map[ENUMERAL_TYPE]);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_enum (type)
|
||||
tree type;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
tree name = TYPE_NAME (type);
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
|
||||
if (context_stack)
|
||||
switch (TREE_CODE (context_stack->context))
|
||||
{
|
||||
case FUNCTION_DECL:
|
||||
return;
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
break;
|
||||
default:
|
||||
my_friendly_abort (30);
|
||||
}
|
||||
else
|
||||
{
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
cadillac_printf ("finish top-level enum", IDENTIFIER_POINTER (name));
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
}
|
||||
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_start_struct (type)
|
||||
tree type;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
tree name = TYPE_NAME (type);
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
|
||||
if (context_stack)
|
||||
switch (TREE_CODE (context_stack->context))
|
||||
{
|
||||
case FUNCTION_DECL:
|
||||
return;
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
return;
|
||||
default:
|
||||
my_friendly_abort (31);
|
||||
}
|
||||
else
|
||||
{
|
||||
cadillac_printf ("start struct", IDENTIFIER_POINTER (name));
|
||||
CWriteTopLevel (conn, StartMType);
|
||||
}
|
||||
|
||||
context_stack = push_context_level (context_stack, &cadillac_obstack);
|
||||
context_stack->context = type;
|
||||
|
||||
CWriteLanguageType (conn, type,
|
||||
TYPE_LANG_SPECIFIC (type) && CLASSTYPE_DECLARED_CLASS (type) ? ClassOType : tree_to_cadillac_map[TREE_CODE (type)]);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_struct (type)
|
||||
tree type;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
tree name = TYPE_NAME (type);
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
|
||||
context_stack = pop_context_level (context_stack);
|
||||
if (context_stack)
|
||||
return;
|
||||
|
||||
cadillac_printf ("finish struct", IDENTIFIER_POINTER (name));
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_exception (type)
|
||||
tree type;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
fatal ("cadillac_finish_exception");
|
||||
CWriteHeader (conn, EndDefMType, 0);
|
||||
CWriteLength (conn);
|
||||
CWriteTopLevel (conn, StopMType);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_push_class (type)
|
||||
tree type;
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_pop_class ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_push_lang (name)
|
||||
tree name;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
CLinkLanguageType m;
|
||||
|
||||
if (name == lang_name_cplusplus)
|
||||
m = LinkCPlus;
|
||||
else if (name == lang_name_c)
|
||||
m = LinkC;
|
||||
else
|
||||
my_friendly_abort (32);
|
||||
CWriteHeader (conn, ForeignLinkageMType, m);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_pop_lang ()
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
CWriteHeader (conn, ForeignLinkageMType, LinkPop);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_finish_stmt ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_note_source ()
|
||||
{
|
||||
cadillacObj.lineno = lineno;
|
||||
cadillacObj.filename = input_filename;
|
||||
}
|
||||
|
||||
static void
|
||||
CWriteTopLevel (conn, m)
|
||||
Connection *conn;
|
||||
CMessageSubType m;
|
||||
{
|
||||
static context_id = 0;
|
||||
CWriteHeader (conn, TopLevelFormMType, m);
|
||||
cadillac_note_filepos ();
|
||||
|
||||
/* Eventually, this will point somewhere into the digest file. */
|
||||
context_id += 1;
|
||||
CWriteSomething (conn, &context_id, sizeof (BITS32));
|
||||
|
||||
CWriteSomething (conn, &cadillacObj.iflevel, sizeof (BITS32));
|
||||
CWriteLength (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
cadillac_note_filepos ()
|
||||
{
|
||||
extern FILE *finput;
|
||||
int pos = ftell (finput);
|
||||
CWriteSomething (cadillacObj.conn, &pos, sizeof (BITS32));
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_switch_source (startflag)
|
||||
int startflag;
|
||||
{
|
||||
Connection *conn = cadillacObj.conn;
|
||||
/* Send out the name of the source file being compiled. */
|
||||
|
||||
CWriteHeader (conn, SourceFileMType, startflag ? StartMType : StopMType);
|
||||
CWriteSomething (conn, &cadillacObj.depth, sizeof (BITS16));
|
||||
CWriteVstring0 (conn, input_filename);
|
||||
CWriteLength (conn);
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_push_source ()
|
||||
{
|
||||
cadillacObj.depth += 1;
|
||||
cadillac_switch_source (1);
|
||||
}
|
||||
|
||||
void
|
||||
cadillac_pop_source ()
|
||||
{
|
||||
cadillacObj.depth -= 1;
|
||||
cadillac_switch_source (0);
|
||||
}
|
||||
|
||||
struct cadillac_mdep
|
||||
{
|
||||
short object_type;
|
||||
char linkage;
|
||||
char access;
|
||||
short length;
|
||||
};
|
||||
|
||||
static void
|
||||
CWriteLanguageElem (conn, p, name)
|
||||
Connection *conn;
|
||||
struct cadillac_mdep *p;
|
||||
char *name;
|
||||
{
|
||||
CWriteSomething (conn, &p->object_type, sizeof (BITS16));
|
||||
CWriteSomething (conn, &p->linkage, sizeof (BITS8));
|
||||
CWriteSomething (conn, &p->access, sizeof (BITS8));
|
||||
CWriteSomething (conn, &p->length, sizeof (BITS16));
|
||||
CWriteVstring0 (conn, name);
|
||||
|
||||
#if 0
|
||||
/* Don't write date_type. */
|
||||
CWriteVstring0 (conn, "");
|
||||
#endif
|
||||
CWriteLength (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
CWriteLanguageDecl (conn, decl, object_type)
|
||||
Connection *conn;
|
||||
tree decl;
|
||||
CObjectType object_type;
|
||||
{
|
||||
struct cadillac_mdep foo;
|
||||
tree name;
|
||||
|
||||
CWriteHeader (conn, LanguageElementMType, StartDefineMType);
|
||||
foo.object_type = object_type;
|
||||
if (decl_type_context (decl))
|
||||
{
|
||||
foo.linkage = ParentLinkage;
|
||||
if (TREE_PRIVATE (decl))
|
||||
foo.access = PrivateAccess;
|
||||
else if (TREE_PROTECTED (decl))
|
||||
foo.access = ProtectedAccess;
|
||||
else
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TREE_PUBLIC (decl))
|
||||
foo.linkage = GlobalLinkage;
|
||||
else
|
||||
foo.linkage = FileLinkage;
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
name = DECL_NAME (decl);
|
||||
foo.length = IDENTIFIER_LENGTH (name);
|
||||
|
||||
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
CWriteLanguageType (conn, type, object_type)
|
||||
Connection *conn;
|
||||
tree type;
|
||||
CObjectType object_type;
|
||||
{
|
||||
struct cadillac_mdep foo;
|
||||
tree name = TYPE_NAME (type);
|
||||
|
||||
CWriteHeader (conn, LanguageElementMType, StartDefineMType);
|
||||
foo.object_type = object_type;
|
||||
if (current_class_type)
|
||||
{
|
||||
foo.linkage = ParentLinkage;
|
||||
if (TREE_PRIVATE (type))
|
||||
foo.access = PrivateAccess;
|
||||
else if (TREE_PROTECTED (type))
|
||||
foo.access = ProtectedAccess;
|
||||
else
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
foo.linkage = NoLinkage;
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
|
||||
foo.length = IDENTIFIER_LENGTH (name);
|
||||
|
||||
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
CWriteUseObject (conn, type, object_type, use)
|
||||
Connection *conn;
|
||||
tree type;
|
||||
CObjectType object_type;
|
||||
CMessageSubType use;
|
||||
{
|
||||
struct cadillac_mdep foo;
|
||||
tree name = NULL_TREE;
|
||||
|
||||
CWriteHeader (conn, LanguageElementMType, use);
|
||||
foo.object_type = object_type;
|
||||
if (current_class_type)
|
||||
{
|
||||
foo.linkage = ParentLinkage;
|
||||
if (TREE_PRIVATE (type))
|
||||
foo.access = PrivateAccess;
|
||||
else if (TREE_PROTECTED (type))
|
||||
foo.access = ProtectedAccess;
|
||||
else
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
foo.linkage = NoLinkage;
|
||||
foo.access = PublicAccess;
|
||||
}
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
case VAR_DECL:
|
||||
case FIELD_DECL:
|
||||
case TYPE_DECL:
|
||||
case CONST_DECL:
|
||||
case FUNCTION_DECL:
|
||||
name = DECL_NAME (type);
|
||||
break;
|
||||
|
||||
default:
|
||||
my_friendly_abort (33);
|
||||
}
|
||||
|
||||
foo.length = IDENTIFIER_LENGTH (name);
|
||||
|
||||
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
|
||||
CWriteRequestBuffer (conn);
|
||||
cadillac_process_requests (conn);
|
||||
}
|
||||
|
||||
/* Here's how we exit under cadillac. */
|
||||
|
||||
static void
|
||||
exit_cadillac ()
|
||||
{
|
||||
extern int errorcount;
|
||||
|
||||
Connection *conn = cadillacObj.conn;
|
||||
|
||||
if (flag_cadillac)
|
||||
{
|
||||
CCompilerMessage *req;
|
||||
|
||||
CWriteHeader (conn, FinishedMType,
|
||||
errorcount ? 0 : CsObjectWritten | CsComplete);
|
||||
/* Bye, bye! */
|
||||
CWriteRequestBuffer (conn);
|
||||
|
||||
/* Block on read. */
|
||||
while (! readable_p (cadillacObj.fd_input))
|
||||
{
|
||||
if (exiting)
|
||||
my_friendly_abort (34);
|
||||
exiting = 1;
|
||||
}
|
||||
exiting = 1;
|
||||
|
||||
req = CReadCompilerMessage (conn);
|
||||
cadillac_process_request (&cadillacObj, req);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/* Stubs. */
|
||||
void init_cadillac () {}
|
||||
void cadillac_start () {}
|
||||
void cadillac_start_decl (decl)
|
||||
tree decl;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_decl (decl)
|
||||
tree decl;
|
||||
{}
|
||||
void
|
||||
cadillac_start_function (fndecl)
|
||||
tree fndecl;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_function (fndecl)
|
||||
tree fndecl;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_anon_union (decl)
|
||||
tree decl;
|
||||
{}
|
||||
void
|
||||
cadillac_start_enum (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_enum (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_start_struct (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_struct (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_finish_exception (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_push_class (type)
|
||||
tree type;
|
||||
{}
|
||||
void
|
||||
cadillac_pop_class ()
|
||||
{}
|
||||
void
|
||||
cadillac_push_lang (name)
|
||||
tree name;
|
||||
{}
|
||||
void
|
||||
cadillac_pop_lang ()
|
||||
{}
|
||||
void
|
||||
cadillac_note_source ()
|
||||
{}
|
||||
void
|
||||
cadillac_finish_stmt ()
|
||||
{}
|
||||
void
|
||||
cadillac_switch_source ()
|
||||
{}
|
||||
void
|
||||
cadillac_push_source ()
|
||||
{}
|
||||
void
|
||||
cadillac_pop_source ()
|
||||
{}
|
||||
#endif
|
||||
1550
contrib/gcc/cp/gc.c
1550
contrib/gcc/cp/gc.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,236 +0,0 @@
|
|||
@node ANSI
|
||||
@chapter @sc{gnu} C++ Conformance to @sc{ansi} C++
|
||||
|
||||
These changes in the @sc{gnu} C++ compiler were made to comply more
|
||||
closely with the @sc{ansi} base document, @cite{The Annotated C++
|
||||
Reference Manual} (the @sc{arm}). Further reducing the divergences from
|
||||
@sc{ansi} C++ is a continued goal of the @sc{gnu} C++ Renovation
|
||||
Project.
|
||||
|
||||
@b{Section 3.4}, @i{Start and Termination}. It is now invalid to take
|
||||
the address of the function @samp{main()}.
|
||||
|
||||
@b{Section 4.8}, @i{Pointers to Members}. The compiler produces
|
||||
an error for trying to convert between a pointer to a member and the type
|
||||
@samp{void *}.
|
||||
|
||||
@b{Section 5.2.5}, @i{Increment and Decrement}. It is an error to use
|
||||
the increment and decrement operators on an enumerated type.
|
||||
|
||||
@b{Section 5.3.2}, @i{Sizeof}. Doing @code{sizeof} on a function is now
|
||||
an error.
|
||||
|
||||
@b{Section 5.3.4}, @i{Delete}. The syntax of a @i{cast-expression} is
|
||||
now more strictly controlled.
|
||||
|
||||
@b{Section 7.1.1}, @i{Storage Class Specifiers}. Using the
|
||||
@code{static} and @code{extern} specifiers can now only be applied to
|
||||
names of objects, functions, and anonymous unions.
|
||||
|
||||
@b{Section 7.1.1}, @i{Storage Class Specifiers}. The compiler no longer complains
|
||||
about taking the address of a variable which has been declared to have @code{register}
|
||||
storage.
|
||||
|
||||
@b{Section 7.1.2}, @i{Function Specifiers}. The compiler produces an
|
||||
error when the @code{inline} or @code{virtual} specifiers are
|
||||
used on anything other than a function.
|
||||
|
||||
@b{Section 8.3}, @i{Function Definitions}. It is now an error to shadow
|
||||
a parameter name with a local variable; in the past, the compiler only
|
||||
gave a warning in such a situation.
|
||||
|
||||
@b{Section 8.4.1}, @i{Aggregates}. The rules concerning declaration of
|
||||
an aggregate are now all checked in the @sc{gnu} C++ compiler; they
|
||||
include having no private or protected members and no base classes.
|
||||
|
||||
@b{Section 8.4.3}, @i{References}. Declaring an array of references is
|
||||
now forbidden. Initializing a reference with an initializer list is
|
||||
also considered an error.
|
||||
|
||||
@b{Section 9.5}, @i{Unions}. Global anonymous unions must be declared
|
||||
@code{static}.
|
||||
|
||||
@b{Section 11.4}, @i{Friends}. Declaring a member to be a friend of a
|
||||
type that has not yet been defined is an error.
|
||||
|
||||
@b{Section 12.1}, @i{Constructors}. The compiler generates a
|
||||
default copy constructor for a class if no constructor has been declared.
|
||||
|
||||
@ignore
|
||||
@b{Section 12.4}, @i{Destructors}. In accordance with the @sc{ansi} C++
|
||||
draft standard working paper, a pure virtual destructor must now be
|
||||
defined.
|
||||
@end ignore
|
||||
|
||||
@b{Section 12.6.2}, @i{Special Member Functions}. When using a
|
||||
@i{mem-initializer} list, the compiler will now initialize class members
|
||||
in declaration order, not in the order in which you specify them.
|
||||
Also, the compiler enforces the rule that non-static @code{const}
|
||||
and reference members must be initialized with a @i{mem-initializer}
|
||||
list when their class does not have a constructor.
|
||||
|
||||
@b{Section 12.8}, @i{Copying Class Objects}. The compiler generates
|
||||
default copy constructors correctly, and supplies default assignment
|
||||
operators compatible with user-defined ones.
|
||||
|
||||
@b{Section 13.4}, @i{Overloaded Operators}. An overloaded operator may
|
||||
no longer have default arguments.
|
||||
|
||||
@b{Section 13.4.4}, @i{Function Call}. An overloaded @samp{operator ()}
|
||||
must be a non-static member function.
|
||||
|
||||
@b{Section 13.4.5}, @i{Subscripting}. An overloaded @samp{operator []}
|
||||
must be a non-static member function.
|
||||
|
||||
@b{Section 13.4.6}, @i{Class Member Access}. An overloaded @samp{operator ->}
|
||||
must be a non-static member function.
|
||||
|
||||
@b{Section 13.4.7}, @i{Increment and Decrement}. The compiler will now
|
||||
make sure a postfix @samp{@w{operator ++}} or @samp{@w{operator --}} has an
|
||||
@code{int} as its second argument.
|
||||
|
||||
|
||||
@node Encoding
|
||||
@chapter Name Encoding in @sc{gnu} C++
|
||||
|
||||
@c FIXME!! rewrite name encoding section
|
||||
@c ...to give complete rules rather than diffs from ARM.
|
||||
@c To avoid plagiarism, invent some different way of structuring the
|
||||
@c description of the rules than what ARM uses.
|
||||
|
||||
@cindex mangling
|
||||
@cindex name encoding
|
||||
@cindex encoding information in names
|
||||
In order to support its strong typing rules and the ability to provide
|
||||
function overloading, the C++ programming language @dfn{encodes}
|
||||
information about functions and objects, so that conflicts across object
|
||||
files can be detected during linking. @footnote{This encoding is also
|
||||
sometimes called, whimsically enough, @dfn{mangling}; the corresponding
|
||||
decoding is sometimes called @dfn{demangling}.} These rules tend to be
|
||||
unique to each individual implementation of C++.
|
||||
|
||||
The scheme detailed in the commentary for 7.2.1 of @cite{The Annotated
|
||||
Reference Manual} offers a description of a possible implementation
|
||||
which happens to closely resemble the @code{cfront} compiler. The
|
||||
design used in @sc{gnu} C++ differs from this model in a number of ways:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
In addition to the basic types @code{void}, @code{char}, @code{short},
|
||||
@code{int}, @code{long}, @code{float}, @code{double}, and @code{long
|
||||
double}, @sc{gnu} C++ supports two additional types: @code{wchar_t}, the wide
|
||||
character type, and @code{long long} (if the host supports it). The
|
||||
encodings for these are @samp{w} and @samp{x} respectively.
|
||||
|
||||
@item
|
||||
According to the @sc{arm}, qualified names (e.g., @samp{foo::bar::baz}) are
|
||||
encoded with a leading @samp{Q}. Followed by the number of
|
||||
qualifications (in this case, three) and the respective names, this
|
||||
might be encoded as @samp{Q33foo3bar3baz}. @sc{gnu} C++ adds a leading
|
||||
underscore to the list, producing @samp{_Q33foo3bar3baz}.
|
||||
|
||||
@item
|
||||
The operator @samp{*=} is encoded as @samp{__aml}, not @samp{__amu}, to
|
||||
match the normal @samp{*} operator, which is encoded as @samp{__ml}.
|
||||
|
||||
@c XXX left out ->(), __wr
|
||||
@item
|
||||
In addition to the normal operators, @sc{gnu} C++ also offers the minimum and
|
||||
maximum operators @samp{>?} and @samp{<?}, encoded as @samp{__mx} and
|
||||
@samp{__mn}, and the conditional operator @samp{?:}, encoded as @samp{__cn}.
|
||||
|
||||
@cindex destructors, encoding of
|
||||
@cindex constructors, encoding of
|
||||
@item
|
||||
Constructors are encoded as simply @samp{__@var{name}}, where @var{name}
|
||||
is the encoded name (e.g., @code{3foo} for the @code{foo} class
|
||||
constructor). Destructors are encoded as two leading underscores
|
||||
separated by either a period or a dollar sign, depending on the
|
||||
capabilities of the local host, followed by the encoded name. For
|
||||
example, the destructor @samp{foo::~foo} is encoded as @samp{_$_3foo}.
|
||||
|
||||
@item
|
||||
Virtual tables are encoded with a prefix of @samp{_vt}, rather than
|
||||
@samp{__vtbl}. The names of their classes are separated by dollar signs
|
||||
(or periods), and not encoded as normal: the virtual table for
|
||||
@code{foo} is @samp{__vt$foo}, and the table for @code{foo::bar} is
|
||||
named @samp{__vt$foo$bar}.
|
||||
|
||||
@item
|
||||
Static members are encoded as a leading underscore, followed by the
|
||||
encoded name of the class in which they appear, a separating dollar sign
|
||||
or period, and finally the unencoded name of the variable. For example,
|
||||
if the class @code{foo} contains a static member @samp{bar}, its
|
||||
encoding would be @samp{_3foo$bar}.
|
||||
|
||||
@item
|
||||
@sc{gnu} C++ is not as aggressive as other compilers when it comes to always
|
||||
generating @samp{Fv} for functions with no arguments. In particular,
|
||||
the compiler does not add the sequence to conversion operators. The
|
||||
function @samp{foo::bar()} is encoded as @samp{bar__3foo}, not
|
||||
@samp{bar__3fooFv}.
|
||||
|
||||
@item
|
||||
The argument list for methods is not prefixed by a leading @samp{F}; it
|
||||
is considered implied.
|
||||
|
||||
@item
|
||||
@sc{gnu} C++ approaches the task of saving space in encodings
|
||||
differently from that noted in the @sc{arm}. It does use the
|
||||
@samp{T@var{n}} and @samp{N@var{x}@var{y}} codes to signify copying the
|
||||
@var{n}th argument's type, and making the next @var{x} arguments be the
|
||||
type of the @var{y}th argument, respectively. However, the values for
|
||||
@var{n} and @var{y} begin at zero with @sc{gnu} C++, whereas the
|
||||
@sc{arm} describes them as starting at one. For the function @samp{foo
|
||||
(bartype, bartype)}, @sc{gnu} C++ uses @samp{foo__7bartypeT0}, while
|
||||
compilers following the @sc{arm} example generate @samp{foo__7bartypeT1}.
|
||||
|
||||
@c Note it loses on `foo (int, int, int, int, int)'.
|
||||
@item
|
||||
@sc{gnu} C++ does not bother using the space-saving methods for types whose
|
||||
encoding is a single character (like an integer, encoded as @samp{i}).
|
||||
This is useful in the most common cases (two @code{int}s would result in
|
||||
using three letters, instead of just @samp{ii}).
|
||||
@end itemize
|
||||
|
||||
@c @node Cfront
|
||||
@c @chapter @code{cfront} Compared to @sc{gnu} C++
|
||||
@c
|
||||
@c
|
||||
@c FIXME!! Fill in. Consider points in the following:
|
||||
@c
|
||||
@c @display
|
||||
@c Date: Thu, 2 Jan 92 21:35:20 EST
|
||||
@c From: raeburn@@cygnus.com
|
||||
@c Message-Id: <9201030235.AA10999@@cambridge.cygnus.com>
|
||||
@c To: mrs@@charlie.secs.csun.edu
|
||||
@c Cc: g++@@cygnus.com
|
||||
@c Subject: Re: ARM and GNU C++ incompatabilities
|
||||
@c
|
||||
@c Along with that, we should probably describe how g++ differs from
|
||||
@c cfront, in ways that the users will notice. (E.g., cfront supposedly
|
||||
@c allows "free (new char[10])"; does g++? How do the template
|
||||
@c implementations differ? "New" placement syntax?)
|
||||
@c @end display
|
||||
@c
|
||||
@c XXX For next revision.
|
||||
@c
|
||||
@c GNU C++:
|
||||
@c * supports expanding inline functions in many situations,
|
||||
@c including those which have static objects, use `for' statements,
|
||||
@c and other situations. Part of this versatility is due to is
|
||||
@c ability to not always generate temporaries for assignments.
|
||||
@c * deliberately allows divide by 0 and mod 0, since [according
|
||||
@c to Wilson] there are actually situations where you'd like to allow
|
||||
@c such things. Note on most systems it will cause some sort of trap
|
||||
@c or bus error. Cfront considers it an error.
|
||||
@c * does [appear to] support nested classes within templates.
|
||||
@c * conversion functions among baseclasses are all usable by
|
||||
@c a class that's derived from all of those bases.
|
||||
@c * sizeof works even when the class is defined within its ()'s
|
||||
@c * conditional expressions work with member fns and pointers to
|
||||
@c members.
|
||||
@c * can handle non-trivial declarations of variables within switch
|
||||
@c statements.
|
||||
@c
|
||||
@c Cfront:
|
||||
|
|
@ -1,235 +0,0 @@
|
|||
@node Templates
|
||||
@chapter The Template Implementation
|
||||
|
||||
@cindex templates
|
||||
@cindex function templates
|
||||
@cindex class templates
|
||||
@cindex parameterized types
|
||||
@cindex types, parameterized
|
||||
The C++ template@footnote{Class templates are also known as
|
||||
@dfn{parameterized types}.} facility, which effectively allows use of
|
||||
variables for types in declarations, is one of the newest features of
|
||||
the language.
|
||||
|
||||
@sc{gnu} C++ is one of the first compilers to implement many
|
||||
of the template facilities currently defined by the @sc{ansi} committee.
|
||||
|
||||
Nevertheless, the template implementation is not yet complete. This
|
||||
chapter maps the current limitations of the @sc{gnu} C++ template
|
||||
implementation.
|
||||
|
||||
@menu
|
||||
* Template limitations:: Limitations for function and class templates
|
||||
* Function templates:: Limitations for function templates
|
||||
* Class templates:: Limitations for class templates
|
||||
* Template debugging:: Debugging information for templates
|
||||
@end menu
|
||||
|
||||
@node Template limitations
|
||||
@section Limitations for function and class templates
|
||||
|
||||
@cindex template limitations
|
||||
@cindex template bugs
|
||||
@cindex bugs, templates
|
||||
These limitations apply to any use of templates (function templates or
|
||||
class templates) with @sc{gnu} C++:
|
||||
|
||||
@table @emph
|
||||
@item Template definitions must be visible
|
||||
When you compile code with templates, the template definitions must come
|
||||
first (before the compiler needs to expand them), and template
|
||||
definitions you use must be visible in the current scope.
|
||||
@c FIXME! Is this a defined property of templates, rather than a
|
||||
@c temporary limitation?
|
||||
@c ANSWER: It's a limitation, but it's hard to say why it's a limitation
|
||||
@c to someone. We need an infinite link-cycle, in one camp, to
|
||||
@c accomplish things so you don't need the template definitions around.
|
||||
|
||||
@cindex static data in template classes
|
||||
@cindex template classes, static data in
|
||||
@item Individual initializers needed for static data
|
||||
Templates for static data in template classes do not work. @xref{Class
|
||||
templates,,Limitations for class templates}.
|
||||
@end table
|
||||
|
||||
@node Function templates
|
||||
@section Limitations for function templates
|
||||
|
||||
@cindex function template limitations
|
||||
Function templates are implemented for the most part. The compiler can
|
||||
correctly determine template parameter values, and will delay
|
||||
instantiation of a function that uses templates until the requisite type
|
||||
information is available.
|
||||
|
||||
@noindent
|
||||
The following limitations remain:
|
||||
|
||||
@itemize @bullet
|
||||
@cindex template vs declaration, functions
|
||||
@cindex declaration vs template, functions
|
||||
@cindex function declaration vs template
|
||||
@item
|
||||
Narrowed specification: function declarations should not prevent
|
||||
template expansion. When you declare a function, @sc{gnu} C++
|
||||
interprets the declaration as an indication that you will provide a
|
||||
definition for that function. Therefore, @sc{gnu} C++ does not use a
|
||||
template expansion if there is also an applicable declaration. @sc{gnu}
|
||||
C++ only expands the template when there is no such declaration.
|
||||
|
||||
The specification in Bjarne Stroustrup's @cite{The C++ Programming
|
||||
Language, Second Edition} is narrower, and the @sc{gnu} C++
|
||||
implementation is now clearly incorrect. With this new specification, a
|
||||
declaration that corresponds to an instantiation of a function template
|
||||
only affects whether conversions are needed to use that version of the
|
||||
function. It should no longer prevent expansion of the template
|
||||
definition.
|
||||
|
||||
For example, this code fragment must be treated differently:
|
||||
|
||||
@smallexample
|
||||
template <class X> X min (X& x1, X& x2) @{ @dots{} @}
|
||||
int min (int, int);
|
||||
@dots{}
|
||||
int i; short s;
|
||||
min (i, s); // @r{should call} min(int,int)
|
||||
// @r{derived from template}
|
||||
@dots{}
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
The compiler does not yet understand function signatures where types are
|
||||
nested within template parameters. For example, a function like the
|
||||
following produces a syntax error on the closing @samp{)} of the
|
||||
definition of the function @code{f}:
|
||||
|
||||
@smallexample
|
||||
template <class T> class A @{ public: T x; class Y @{@}; @};
|
||||
template <class X> int f (A<X>::Y y) @{ @dots{} @}
|
||||
@end smallexample
|
||||
|
||||
@cindex @code{inline} and function templates
|
||||
@cindex function templates and @code{inline}
|
||||
@item
|
||||
If you declare an @code{inline} function using templates, the compiler
|
||||
can only inline the code @emph{after} the first time you use
|
||||
that function with whatever particular type signature the template
|
||||
was instantiated.
|
||||
|
||||
Removing this limitation is akin to supporting nested function
|
||||
definitions in @sc{gnu} C++; the limitation will probably remain until the
|
||||
more general problem of nested functions is solved.
|
||||
|
||||
@item
|
||||
All the @emph{method} templates (templates for member functions) for a
|
||||
class must be visible to the compiler when the class template is
|
||||
instantiated.
|
||||
@end itemize
|
||||
|
||||
@node Class templates
|
||||
@section Limitations for class templates
|
||||
|
||||
@cindex class template limitations
|
||||
@ignore
|
||||
FIXME!! Include a comprehensible version of this if someone can explain it.
|
||||
(Queried Brendan and Raeburn w/full orig context, 26may1993---pesch)
|
||||
- [RHP: I don't understand what the following fragment refers to. If it's
|
||||
the "BIG BUG" section in the original, why does it say "overriding class
|
||||
declarations" here when the more detailed text refers to *function*
|
||||
declarations? Here's the fragment I don't understand:]
|
||||
there are problems with user-supplied overriding class declarations (see
|
||||
below).
|
||||
@end ignore
|
||||
|
||||
@itemize @bullet
|
||||
@ignore
|
||||
@cindex static data, not working in templates
|
||||
@item
|
||||
Templates for static data in template classes do not work.
|
||||
Currently, you must initialize each case of such data
|
||||
individually.
|
||||
@c FIXME!! Brendan to see if still true.
|
||||
@c ANSWER: This section presumes that it's incorrect to have to
|
||||
@c initialize for each type you instantiate with. It's not, it's the
|
||||
@c right way to do it.
|
||||
@end ignore
|
||||
|
||||
Unfortunately, individual initializations of this sort are likely to be
|
||||
considered errors eventually; since they're needed now, you might want to
|
||||
flag places where you use them with comments to mark the need for a
|
||||
future transition.
|
||||
|
||||
@cindex nested type results vs templates
|
||||
@item
|
||||
Member functions in template classes may not have results of nested
|
||||
type; @sc{gnu} C++ signals a syntax error on the attempt. The following
|
||||
example illustrates this problem with an @code{enum} type @code{alph}:
|
||||
|
||||
@smallexample
|
||||
template <class T> class list @{
|
||||
@dots{}
|
||||
enum alph @{a,b,c@};
|
||||
alph bar();
|
||||
@dots{}
|
||||
@};
|
||||
|
||||
template <class T>
|
||||
list<int>::alph list<int>::bar() // @i{Syntax error here}
|
||||
@{
|
||||
@dots{}
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
@cindex preprocessor conditionals in templates
|
||||
@cindex conditionals (preprocessor) in templates
|
||||
@item
|
||||
A parsing bug makes it difficult to use preprocessor conditionals within
|
||||
templates. For example, in this code:
|
||||
|
||||
@smallexample
|
||||
template <class T>
|
||||
class list @{
|
||||
@dots{}
|
||||
#ifdef SYSWRONG
|
||||
T x;
|
||||
#endif
|
||||
@dots{}
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
The preprocessor output leaves sourcefile line number information (lines
|
||||
like @samp{# 6 "foo.cc"} when it expands the @code{#ifdef} block. These
|
||||
lines confuse the compiler while parsing templates, giving a syntax
|
||||
error.
|
||||
|
||||
If you cannot avoid preprocessor conditionals in templates, you can
|
||||
suppress the line number information using the @samp{-P} preprocessor
|
||||
option (but this will make debugging more difficult), by compiling the
|
||||
affected modules like this:
|
||||
|
||||
@smallexample
|
||||
g++ -P foo.cc -o foo
|
||||
@end smallexample
|
||||
|
||||
@cindex parsing errors, templates
|
||||
@item
|
||||
Parsing errors are reported when templates are first
|
||||
@emph{instantiated}---not on the template definition itself. In
|
||||
particular, if you do not instantiate a template definition at all, the
|
||||
compiler never reports any parsing errors that may be in the template
|
||||
definition.
|
||||
@end itemize
|
||||
|
||||
@node Template debugging
|
||||
@section Debugging information for templates
|
||||
|
||||
@cindex templates and debugging information
|
||||
@cindex debugging information and templates
|
||||
Debugging information for templates works for some object code formats,
|
||||
but not others. It works for stabs@footnote{Except that insufficient
|
||||
debugging information for methods of template classes is generated in
|
||||
stabs.} (used primarily in @sc{a.out} object code, but also in the Solaris 2
|
||||
version of @sc{elf}), and the @sc{mips} version of @sc{coff} debugging
|
||||
format.
|
||||
|
||||
@sc{dwarf} support is currently minimal, and requires further
|
||||
development.
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/* This file contains the definitions and documentation for the
|
||||
additional tree codes used in the GNU C++ compiler (see tree.def
|
||||
for the standard codes).
|
||||
Copyright (C) 1987, 1988, 1990, 1993 Free Software Foundation, Inc.
|
||||
Hacked by Michael Tiemann (tiemann@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
/* Reference to the contents of an offset
|
||||
(a value whose type is an OFFSET_TYPE).
|
||||
Operand 0 is the object within which the offset is taken.
|
||||
Operand 1 is the offset. The language independent OFFSET_REF
|
||||
just won't work for us. */
|
||||
DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
|
||||
|
||||
/* For DELETE_EXPR, operand 0 is the store to be destroyed.
|
||||
Operand 1 is the value to pass to the destroying function
|
||||
saying whether the store should be deallocated as well. */
|
||||
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
|
||||
DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
|
||||
|
||||
/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
|
||||
mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
|
||||
WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected
|
||||
from being evaluated more than once should be reset so that a new
|
||||
expand_expr call of this expr will cause those to be re-evaluated.
|
||||
This is useful when we want to reuse a tree in different places,
|
||||
but where we must re-expand. */
|
||||
DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
|
||||
|
||||
/* Value is reference to particular overloaded class method.
|
||||
Operand 0 is the class name (an IDENTIFIER_NODE);
|
||||
operand 1 is the field (also an IDENTIFIER_NODE).
|
||||
The COMPLEXITY field holds the class level (usually 0). */
|
||||
DEFTREECODE (SCOPE_REF, "scope_ref", "r", 2)
|
||||
|
||||
/* When composing an object with a member, this is the result.
|
||||
Operand 0 is the object. Operand 1 is the member (usually
|
||||
a dereferenced pointer to member). */
|
||||
DEFTREECODE (MEMBER_REF, "member_ref", "r", 2)
|
||||
|
||||
/* Type conversion operator in C++. TREE_TYPE is type that this
|
||||
operator converts to. Operand is expression to be converted. */
|
||||
DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
|
||||
|
||||
/* For CPLUS_NEW_EXPR, operand 0 is function which performs initialization,
|
||||
operand 1 is argument list to initialization function,
|
||||
and operand 2 is the slot which was allocated for this expression. */
|
||||
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
|
||||
DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3)
|
||||
|
||||
/* A throw expression. operand 0 is the expression, if there was one,
|
||||
else it is NULL_TREE. */
|
||||
DEFTREECODE (THROW_EXPR, "throw_expr", "e", 1)
|
||||
|
||||
/* Template definition. The following fields have the specified uses,
|
||||
although there are other macros in cp-tree.h that should be used for
|
||||
accessing this data.
|
||||
DECL_ARGUMENTS template parm vector
|
||||
DECL_TEMPLATE_INFO template text &c
|
||||
DECL_VINDEX list of instantiations already produced;
|
||||
only done for functions so far
|
||||
For class template:
|
||||
DECL_INITIAL associated templates (methods &c)
|
||||
DECL_RESULT null
|
||||
For non-class templates:
|
||||
TREE_TYPE type of object to be constructed
|
||||
DECL_RESULT decl for object to be created
|
||||
(e.g., FUNCTION_DECL with tmpl parms used)
|
||||
*/
|
||||
DEFTREECODE (TEMPLATE_DECL, "template_decl", "d", 0)
|
||||
|
||||
/* Index into a template parameter list. This parameter must be a type.
|
||||
Use TYPE_FIELDS to find parmlist and index. */
|
||||
DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", "t", 0)
|
||||
|
||||
/* Index into a template parameter list. This parameter must not be a
|
||||
type. */
|
||||
DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
|
||||
|
||||
/* For uninstantiated parameterized types.
|
||||
TYPE_VALUES tree list:
|
||||
TREE_PURPOSE template decl
|
||||
TREE_VALUE parm vector
|
||||
TREE_CHAIN null
|
||||
Other useful fields to be defined later. */
|
||||
DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)
|
||||
|
||||
/* A thunk is a stub function.
|
||||
|
||||
Thunks are used to implement multiple inheritance:
|
||||
At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree)
|
||||
from the this pointer, and then jumps to DECL_INITIAL
|
||||
(which is an ADDR_EXPR whose operand is a FUNCTION_DECL).
|
||||
|
||||
Other kinds of thunks may be defined later. */
|
||||
DEFTREECODE (THUNK_DECL, "thunk_decl", "d", 0)
|
||||
|
||||
/* A namespace declaration. */
|
||||
DEFTREECODE (NAMESPACE_DECL, "namespace_decl", "d", 0)
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# modified for dgux by hassey@dg-rtp.dg.com based on
|
||||
#
|
||||
# fixinc.svr4 written by Ron Guilmette (rfg@ncd.com).
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
# See README-fixinc for more information.
|
||||
|
||||
# Directory containing the original header files.
|
||||
INPUT=${2-${INPUT-/usr/include}}
|
||||
|
||||
# Fail if no arg to specify a directory for the output.
|
||||
if [ x$1 = x ]
|
||||
then echo fixincludes: no output directory specified
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Directory in which to store the results.
|
||||
LIB=${1?"fixincludes: output directory not specified"}
|
||||
|
||||
# Make sure it exists.
|
||||
if [ ! -d $LIB ]; then
|
||||
mkdir $LIB || exit 1
|
||||
fi
|
||||
|
||||
ORIG_DIR=`pwd`
|
||||
|
||||
# Make LIB absolute if it is relative.
|
||||
# Don't do this if not necessary, since may screw up automounters.
|
||||
case $LIB in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
cd $LIB; LIB=`${PWDCMD-pwd}`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo 'Building fixincludes in ' ${LIB}
|
||||
|
||||
# Determine whether this filesystem has symbolic links.
|
||||
if ln -s X $LIB/ShouldNotExist 2>/dev/null; then
|
||||
rm -f $LIB/ShouldNotExist
|
||||
LINKS=true
|
||||
else
|
||||
LINKS=false
|
||||
fi
|
||||
|
||||
echo 'Making directories:'
|
||||
cd ${INPUT}
|
||||
if $LINKS; then
|
||||
files=`ls -LR | sed -n s/:$//p`
|
||||
else
|
||||
files=`find . -type d -print | sed '/^.$/d'`
|
||||
fi
|
||||
for file in $files; do
|
||||
rm -rf $LIB/$file
|
||||
if [ ! -d $LIB/$file ]
|
||||
then mkdir $LIB/$file
|
||||
fi
|
||||
done
|
||||
|
||||
# treetops gets an alternating list
|
||||
# of old directories to copy
|
||||
# and the new directories to copy to.
|
||||
treetops="${INPUT} ${LIB}"
|
||||
|
||||
if $LINKS; then
|
||||
echo 'Making internal symbolic directory links'
|
||||
for file in $files; do
|
||||
dest=`ls -ld $file | sed -n 's/.*-> //p'`
|
||||
if [ "$dest" ]; then
|
||||
cwd=`pwd`
|
||||
# In case $dest is relative, get to $file's dir first.
|
||||
cd ${INPUT}
|
||||
cd `echo ./$file | sed -n 's&[^/]*$&&p'`
|
||||
# Check that the target directory exists.
|
||||
# Redirections changed to avoid bug in sh on Ultrix.
|
||||
(cd $dest) > /dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
cd $dest
|
||||
# X gets the dir that the link actually leads to.
|
||||
x=`pwd`
|
||||
# If link leads back into ${INPUT},
|
||||
# make a similar link here.
|
||||
if expr $x : "${INPUT}/.*" > /dev/null; then
|
||||
# Y gets the actual target dir name, relative to ${INPUT}.
|
||||
y=`echo $x | sed -n "s&${INPUT}/&&p"`
|
||||
# DOTS is the relative path from ${LIB}/$file's dir back to ${LIB}.
|
||||
dots=`echo "$file" |
|
||||
sed -e 's@^./@@' -e 's@/./@/@g' -e 's@[^/][^/]*@..@g' -e 's@..$@@'`
|
||||
echo $file '->' $dots$y ': Making link'
|
||||
rm -fr ${LIB}/$file > /dev/null 2>&1
|
||||
ln -s $dots$y ${LIB}/$file > /dev/null 2>&1
|
||||
else
|
||||
# If the link is to outside ${INPUT},
|
||||
# treat this directory as if it actually contained the files.
|
||||
# This line used to have $dest instead of $x.
|
||||
# $dest seemed to be wrong for links found in subdirectories
|
||||
# of ${INPUT}. Does this change break anything?
|
||||
treetops="$treetops $x ${LIB}/$file"
|
||||
fi
|
||||
fi
|
||||
cd $cwd
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Completely replace <_int_varargs.h> with a file that defines
|
||||
# va_list and gnuc_va_list
|
||||
|
||||
file=_int_varargs.h
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
echo Replacing $file
|
||||
cat > ${LIB}/$file << EOF
|
||||
/* This file was generated by fixinc.dgux. */
|
||||
#ifndef __INT_VARARGS_H
|
||||
#define __INT_VARARGS_H
|
||||
|
||||
#if defined(__m88k__) && defined (__DGUX__)
|
||||
#ifndef __GNUC_VA_LIST
|
||||
#define __GNUC_VA_LIST
|
||||
typedef struct
|
||||
{
|
||||
int __va_arg; /* argument number */
|
||||
int *__va_stk; /* start of args passed on stack */
|
||||
int *__va_reg; /* start of args passed in regs */
|
||||
} __gnuc_va_list;
|
||||
#endif /* not __GNUC_VA_LIST */
|
||||
#endif /* 88k && dgux */
|
||||
|
||||
#ifndef _VA_LIST_
|
||||
#define _VA_LIST_
|
||||
typedef __gnuc_va_list va_list;
|
||||
#endif /* _VA_LIST_ */
|
||||
|
||||
#endif /* __INT_VARARGS_H */
|
||||
|
||||
EOF
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
|
||||
echo 'Removing unneeded directories:'
|
||||
cd $LIB
|
||||
files=`find . -type d -print | sort -r`
|
||||
for file in $files; do
|
||||
rmdir $LIB/$file > /dev/null 2>&1
|
||||
done
|
||||
|
||||
if $LINKS; then
|
||||
echo 'Making internal symbolic non-directory links'
|
||||
cd ${INPUT}
|
||||
files=`find . -type l -print`
|
||||
for file in $files; do
|
||||
dest=`ls -ld $file | sed -n 's/.*-> //p'`
|
||||
if expr "$dest" : '[^/].*' > /dev/null; then
|
||||
target=${LIB}/`echo file | sed "s|[^/]*\$|$dest|"`
|
||||
if [ -f $target ]; then
|
||||
ln -s $dest ${LIB}/$file >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
cd ${ORIG_DIR}
|
||||
|
||||
exit 0
|
||||
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Install modified versions of certain ANSI-incompatible
|
||||
# native Sequent DYNIX/ptx System V Release 3.2 system include files.
|
||||
# Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
|
||||
# Contributed by Bill Burton <billb@progress.com>
|
||||
# Portions adapted from fixinc.svr4 and fixincludes.
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# This script munges the native include files provided with DYNIX/ptx
|
||||
# so as to remove things which are violations of the ANSI C standard.
|
||||
# This is done by first running fixinc.svr4 which does most of the
|
||||
# work. A few includes have fixes made to them afterwards by this
|
||||
# script. Once munged, the resulting new system include files are
|
||||
# placed in a directory that GNU C will search *before* searching the
|
||||
# /usr/include directory. This script should work properly for most
|
||||
# DYNIX/ptx systems. For other types of systems, you should use the
|
||||
# `fixincludes' script instead.
|
||||
#
|
||||
# See README-fixinc for more information.
|
||||
|
||||
# Directory containing the original header files.
|
||||
INPUT=${2-${INPUT-/usr/include}}
|
||||
|
||||
# Fail if no arg to specify a directory for the output.
|
||||
if [ x$1 = x ]
|
||||
then echo fixincludes: no output directory specified
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Directory in which to store the results.
|
||||
LIB=${1?"fixincludes: output directory not specified"}
|
||||
|
||||
# Make sure it exists.
|
||||
if [ ! -d $LIB ]; then
|
||||
mkdir $LIB || exit 1
|
||||
fi
|
||||
|
||||
ORIG_DIR=`pwd`
|
||||
|
||||
# Make LIB absolute if it is relative.
|
||||
# Don't do this if not necessary, since may screw up automounters.
|
||||
case $LIB in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
LIB=$ORIG_DIR/$LIB
|
||||
;;
|
||||
esac
|
||||
|
||||
echo 'Running fixinc.svr4'
|
||||
# DYNIX/ptx has dirname so this is no problem
|
||||
`dirname $0`/fixinc.svr4 $*
|
||||
echo 'Finished fixinc.svr4'
|
||||
|
||||
echo 'Building fixincludes in ' ${LIB}
|
||||
|
||||
# Copied from fixincludes.
|
||||
# Don't use or define the name va_list in stdio.h.
|
||||
# This is for ANSI and also to interoperate properly with gcc's varargs.h.
|
||||
file=stdio.h
|
||||
if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
|
||||
cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w ${LIB}/$file 2>/dev/null
|
||||
chmod a+r ${LIB}/$file 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
echo Fixing $file, use of va_list
|
||||
# Arrange for stdio.h to use stdarg.h to define __gnuc_va_list
|
||||
(echo "#define __need___va_list"
|
||||
echo "#include <stdarg.h>") > ${LIB}/${file}.sed
|
||||
# Use __gnuc_va_list in arg types in place of va_list.
|
||||
# On 386BSD use __gnuc_va_list instead of _VA_LIST_. We're hoping the
|
||||
# trailing parentheses and semicolon save all other systems from this.
|
||||
# Define __va_list__ (something harmless and unused) instead of va_list.
|
||||
# Don't claim to have defined va_list.
|
||||
sed -e 's@ va_list @ __gnuc_va_list @' \
|
||||
-e 's@ va_list)@ __gnuc_va_list)@' \
|
||||
-e 's@ _VA_LIST_));@ __gnuc_va_list));@' \
|
||||
-e 's@ va_list@ __va_list__@' \
|
||||
-e 's@\*va_list@*__va_list__@' \
|
||||
-e 's@ __va_list)@ __gnuc_va_list)@' \
|
||||
-e 's@_NEED___VA_LIST@_NEED___Va_LIST@' \
|
||||
-e 's@VA_LIST@DUMMY_VA_LIST@' \
|
||||
-e 's@_NEED___Va_LIST@_NEED___VA_LIST@' \
|
||||
${LIB}/$file >> ${LIB}/${file}.sed
|
||||
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
if cmp $file ${LIB}/$file >/dev/null 2>&1; then
|
||||
rm -f ${LIB}/$file
|
||||
fi
|
||||
fi
|
||||
|
||||
# In pwd.h, PTX 1.x needs stdio.h included since FILE * was added in a
|
||||
# prototype later on in the file.
|
||||
file=pwd.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
if grep stdio $file_to_fix > /dev/null; then
|
||||
true
|
||||
else
|
||||
sed -e '/#include <sys\/types\.h>/a\
|
||||
\
|
||||
#if defined(__STDC__) || defined(__cplusplus)\
|
||||
#include <stdio.h>\
|
||||
#endif /* __STDC__ */
|
||||
' \
|
||||
$file_to_fix > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
echo Fixed $file_to_fix
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copied from fixincludes.
|
||||
# math.h puts the declaration of matherr before the definition
|
||||
# of struct exception, so the prototype (added by fixproto) causes havoc.
|
||||
file=math.h
|
||||
if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
|
||||
cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w ${LIB}/$file 2>/dev/null
|
||||
chmod a+r ${LIB}/$file 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
echo Fixing $file, matherr declaration
|
||||
sed -e '/^struct exception/,$b' \
|
||||
-e '/matherr/i\
|
||||
struct exception;
|
||||
'\
|
||||
${LIB}/$file > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
if cmp $file ${LIB}/$file >/dev/null 2>&1; then
|
||||
rm -f ${LIB}/$file
|
||||
fi
|
||||
fi
|
||||
|
||||
# In netinet/in.h, the network byte swapping asm functions supported by the
|
||||
# native cc compiler on PTX 1.x and 2.x is not supported in gcc. Instead,
|
||||
# include <sys/byteorder.h> written out by the fixinc.svr4 script which has
|
||||
# these same routines written in an asm format supported by gcc.
|
||||
file=netinet/in.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
if grep __GNUC__ $file_to_fix > /dev/null; then
|
||||
true
|
||||
else
|
||||
sed -e '/#define NETSWAP/a\
|
||||
\
|
||||
#if defined (__GNUC__) || defined (__GNUG__)\
|
||||
#include <sys/byteorder.h>\
|
||||
#else /* not __GNUC__ */
|
||||
' \
|
||||
-e '/#endif[ ]*\/\* NETSWAP \*\//i\
|
||||
#endif /* not __GNUC__ */
|
||||
' \
|
||||
$file_to_fix > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
echo Fixed $file_to_fix
|
||||
fi
|
||||
fi
|
||||
|
||||
# /usr/include/sys/mc_param.h has an embedded asm for the cpuid instruction
|
||||
# on the P5. This is not used by anything else so we ifdef it out.
|
||||
file=sys/mc_param.h
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
if grep __GNUC__ $file_to_fix > /dev/null; then
|
||||
true
|
||||
else
|
||||
sed -e '/__asm/,/}/{
|
||||
/__asm/i\
|
||||
#if !defined (__GNUC__) && !defined (__GNUG__)
|
||||
/}/a\
|
||||
#endif
|
||||
}' \
|
||||
$file_to_fix > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
echo Fixed $file_to_fix
|
||||
fi
|
||||
fi
|
||||
|
||||
# /usr/include/sys/mc_param.h has an embedded asm for the cpuid instruction
|
||||
# on the P5. This is not used by anything else so we ifdef it out.
|
||||
file=sys/mc_param.h
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
if grep __GNUC__ $file_to_fix > /dev/null; then
|
||||
true
|
||||
else
|
||||
sed -e '/__asm/,/}/{
|
||||
/__asm/i\
|
||||
#if !defined (__GNUC__) && !defined (__GNUG__)
|
||||
/}/a\
|
||||
#endif
|
||||
}' \
|
||||
$file_to_fix > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
echo Fixed $file_to_fix
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
|
|
@ -1,427 +0,0 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# fixinc.sco -- Install modified versions of SCO system include
|
||||
# files.
|
||||
#
|
||||
# Based on fixinc.svr4 script by Ron Guilmette (rfg@ncd.com) (SCO
|
||||
# modifications by Ian Lance Taylor (ian@airs.com)).
|
||||
#
|
||||
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# This script munges the native include files provided with SCO
|
||||
# 3.2v4 systems so as to provide a reasonable namespace when
|
||||
# compiling with gcc. The header files by default do not
|
||||
# provide many essential definitions and declarations if
|
||||
# __STDC__ is 1. This script modifies the header files to check
|
||||
# for __STRICT_ANSI__ being defined instead. Once munged, the
|
||||
# resulting new system include files are placed in a directory
|
||||
# that GNU C will search *before* searching the /usr/include
|
||||
# directory. This script should work properly for most SCO
|
||||
# 3.2v4 systems. For other types of systems, you should use the
|
||||
# `fixincludes' or the `fixinc.svr4' script instead.
|
||||
#
|
||||
# See README-fixinc for more information.
|
||||
|
||||
# Directory containing the original header files.
|
||||
INPUT=${2-${INPUT-/usr/include}}
|
||||
|
||||
# Fail if no arg to specify a directory for the output.
|
||||
if [ x$1 = x ]
|
||||
then echo fixincludes: no output directory specified
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Directory in which to store the results.
|
||||
LIB=${1?"fixincludes: output directory not specified"}
|
||||
|
||||
# Make sure it exists.
|
||||
if [ ! -d $LIB ]; then
|
||||
mkdir $LIB || exit 1
|
||||
fi
|
||||
|
||||
ORIG_DIR=`pwd`
|
||||
|
||||
# Make LIB absolute if it is relative.
|
||||
# Don't do this if not necessary, since may screw up automounters.
|
||||
case $LIB in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
cd $LIB; LIB=`${PWDCMD-pwd}`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo 'Building fixincludes in ' ${LIB}
|
||||
|
||||
# Determine whether this filesystem has symbolic links.
|
||||
if ln -s X $LIB/ShouldNotExist 2>/dev/null; then
|
||||
rm -f $LIB/ShouldNotExist
|
||||
LINKS=true
|
||||
else
|
||||
LINKS=false
|
||||
fi
|
||||
|
||||
echo 'Making directories:'
|
||||
cd ${INPUT}
|
||||
if $LINKS; then
|
||||
files=`ls -LR | sed -n s/:$//p`
|
||||
else
|
||||
files=`find . -type d -print | sed '/^.$/d'`
|
||||
fi
|
||||
for file in $files; do
|
||||
rm -rf $LIB/$file
|
||||
if [ ! -d $LIB/$file ]
|
||||
then mkdir $LIB/$file
|
||||
fi
|
||||
done
|
||||
|
||||
# treetops gets an alternating list
|
||||
# of old directories to copy
|
||||
# and the new directories to copy to.
|
||||
treetops="${INPUT} ${LIB}"
|
||||
|
||||
if $LINKS; then
|
||||
echo 'Making internal symbolic directory links'
|
||||
for file in $files; do
|
||||
dest=`ls -ld $file | sed -n 's/.*-> //p'`
|
||||
if [ "$dest" ]; then
|
||||
cwd=`pwd`
|
||||
# In case $dest is relative, get to $file's dir first.
|
||||
cd ${INPUT}
|
||||
cd `echo ./$file | sed -n 's&[^/]*$&&p'`
|
||||
# Check that the target directory exists.
|
||||
# Redirections changed to avoid bug in sh on Ultrix.
|
||||
(cd $dest) > /dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
cd $dest
|
||||
# X gets the dir that the link actually leads to.
|
||||
x=`pwd`
|
||||
# If link leads back into ${INPUT},
|
||||
# make a similar link here.
|
||||
if expr $x : "${INPUT}/.*" > /dev/null; then
|
||||
# Y gets the actual target dir name, relative to ${INPUT}.
|
||||
y=`echo $x | sed -n "s&${INPUT}/&&p"`
|
||||
echo $file '->' $y ': Making link'
|
||||
rm -fr ${LIB}/$file > /dev/null 2>&1
|
||||
ln -s ${LIB}/$y ${LIB}/$file > /dev/null 2>&1
|
||||
else
|
||||
# If the link is to outside ${INPUT},
|
||||
# treat this directory as if it actually contained the files.
|
||||
# This line used to have $dest instead of $x.
|
||||
# $dest seemed to be wrong for links found in subdirectories
|
||||
# of ${INPUT}. Does this change break anything?
|
||||
treetops="$treetops $x ${LIB}/$file"
|
||||
fi
|
||||
fi
|
||||
cd $cwd
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
set - $treetops
|
||||
while [ $# != 0 ]; do
|
||||
# $1 is an old directory to copy, and $2 is the new directory to copy to.
|
||||
echo "Finding header files in $1:"
|
||||
cd ${INPUT}
|
||||
cd $1
|
||||
files=`find . -name '*.h' -type f -print`
|
||||
echo 'Checking header files:'
|
||||
for file in $files; do
|
||||
if egrep '!__STDC__' $file >/dev/null; then
|
||||
if [ -r $file ]; then
|
||||
cp $file $2/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w $2/$file
|
||||
chmod a+r $2/$file
|
||||
|
||||
# The following have been removed from the sed command below
|
||||
# because it is more useful to leave these things in.
|
||||
# The only reason to remove them was for -pedantic,
|
||||
# which isn't much of a reason. -- rms.
|
||||
# /^[ ]*#[ ]*ident/d
|
||||
|
||||
sed -e '
|
||||
s/!__STDC__/!defined (__STRICT_ANSI__)/g
|
||||
' $2/$file > $2/$file.sed
|
||||
mv $2/$file.sed $2/$file
|
||||
if cmp $file $2/$file >/dev/null 2>&1; then
|
||||
rm $2/$file
|
||||
else
|
||||
echo Fixed $file
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
shift; shift
|
||||
done
|
||||
|
||||
# We shouldn't stay in the directory we just copied.
|
||||
cd ${INPUT}
|
||||
|
||||
# Fix first broken decl of getcwd present on some svr4 systems.
|
||||
|
||||
file=stdlib.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e 's/getcwd(char \{0,\}\*, int)/getcwd(char *, size_t)/' $file_to_fix > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
# Fix second broken decl of getcwd present on some svr4 systems. Also
|
||||
# fix the incorrect decl of profil present on some svr4 systems.
|
||||
|
||||
file=unistd.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e 's/getcwd(char \*, int)/getcwd(char *, size_t)/' $file_to_fix \
|
||||
| sed -e 's/profil(unsigned short \*, unsigned int, unsigned int, unsigned int)/profil(unsigned short *, size_t, int, unsigned)/' > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
# Fix third broken decl of getcwd on SCO. Also fix incorrect decl of
|
||||
# link.
|
||||
file=prototypes.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e 's/getcwd(char \*, int)/getcwd(char *, size_t)/' $file_to_fix \
|
||||
| sed -e 's/const int link(const char \*, char \*)/extern int link(const char *, const char *)/' > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
# Fix an error in this file: the #if says _cplusplus, not the double
|
||||
# underscore __cplusplus that it should be
|
||||
file=tinfo.h
|
||||
if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
|
||||
mkdir ${LIB}/rpcsvc 2>/dev/null
|
||||
cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w ${LIB}/$file 2>/dev/null
|
||||
chmod a+r ${LIB}/$file 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
echo Fixing $file, __cplusplus macro
|
||||
sed -e 's/[ ]_cplusplus/ __cplusplus/' ${LIB}/$file > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
if cmp $file ${LIB}/$file >/dev/null 2>&1; then
|
||||
rm ${LIB}/$file
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fix prototype declaration of utime in sys/times.h. In 3.2v4.0 the
|
||||
# const is missing.
|
||||
file=sys/times.h
|
||||
if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
|
||||
cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w ${LIB}/$file 2>/dev/null
|
||||
chmod a+r ${LIB}/$file 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
echo Fixing $file, utime prototype
|
||||
sed -e 's/(const char \*, struct utimbuf \*);/(const char *, const struct utimbuf *);/' ${LIB}/$file > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
if cmp $file ${LIB}/$file >/dev/null 2>&1; then
|
||||
rm ${LIB}/$file
|
||||
fi
|
||||
fi
|
||||
|
||||
# This function is borrowed from fixinclude.svr4
|
||||
# The OpenServer math.h defines struct exception, which conflicts with
|
||||
# the class exception defined in the C++ file std/stdexcept.h. We
|
||||
# redefine it to __math_exception. This is not a great fix, but I
|
||||
# haven't been able to think of anything better.
|
||||
#
|
||||
# OpenServer's math.h declares abs as inline int abs... Unfortunately,
|
||||
# we blow over that one (with C++ linkage) and stick a new one in stdlib.h
|
||||
# with C linkage. So we eat the one out of math.h.
|
||||
file=math.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e '/struct exception/i\
|
||||
#ifdef __cplusplus\
|
||||
#define exception __math_exception\
|
||||
#endif'\
|
||||
-e '/struct exception/a\
|
||||
#ifdef __cplusplus\
|
||||
#undef exception\
|
||||
#endif' \
|
||||
-e 's@inline int abs(int [a-z][a-z]*) {.*}@extern "C" int abs(int);@' \
|
||||
$file_to_fix > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
#
|
||||
# Also, the static functions lstat() and fchmod() in <sys/stat.h>
|
||||
# cause G++ grief since they're not wrapped in "if __cplusplus".
|
||||
# Fix that up now.
|
||||
#
|
||||
file=sys/stat.h
|
||||
if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
|
||||
cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
|
||||
chmod +w ${LIB}/$file 2>/dev/null
|
||||
chmod a+r ${LIB}/$file 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
echo Fixing $file, static definitions not C++-aware.
|
||||
sed -e '/^static int[ ]*/i\
|
||||
#if __cplusplus\
|
||||
extern "C"\
|
||||
{\
|
||||
#endif /* __cplusplus */ \
|
||||
' \
|
||||
-e '/^}$/a\
|
||||
#if __cplusplus\
|
||||
}\
|
||||
#endif /* __cplusplus */ \
|
||||
' ${LIB}/$file > ${LIB}/${file}.sed
|
||||
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
|
||||
if cmp $file ${LIB}/$file >/dev/null 2>&1; then
|
||||
rm -f ${LIB}/$file
|
||||
fi
|
||||
fi
|
||||
|
||||
# This fix has the regex modified from the from fixinc.wrap
|
||||
# Avoid the definition of the bool type in the following files when using
|
||||
# g++, since it's now an official type in the C++ language.
|
||||
for file in term.h tinfo.h
|
||||
do
|
||||
if [ -r $INPUT/$file ]; then
|
||||
echo Checking $INPUT/$file
|
||||
w='[ ]'
|
||||
if grep "typedef$w.*char$w.*bool$w*;" $INPUT/$file >/dev/null
|
||||
then
|
||||
echo Fixed $file
|
||||
rm -f $LIB/$file
|
||||
cat << __EOF__ >$LIB/$file
|
||||
#ifndef _CURSES_H_WRAPPER
|
||||
#ifdef __cplusplus
|
||||
# define bool __curses_bool_t
|
||||
#endif
|
||||
#include_next <$file>
|
||||
#ifdef __cplusplus
|
||||
# undef bool
|
||||
#endif
|
||||
#define _CURSES_H_WRAPPER
|
||||
#endif /* _CURSES_H_WRAPPER */
|
||||
__EOF__
|
||||
# Define _CURSES_H_WRAPPER at the end of the wrapper, not the start,
|
||||
# so that if #include_next gets another instance of the wrapper,
|
||||
# this will follow the #include_next chain until we arrive at
|
||||
# the real system include file.
|
||||
chmod a+r $LIB/$file
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo 'Removing unneeded directories:'
|
||||
cd $LIB
|
||||
files=`find . -type d -print | sort -r`
|
||||
for file in $files; do
|
||||
rmdir $LIB/$file > /dev/null 2>&1
|
||||
done
|
||||
|
||||
if $LINKS; then
|
||||
echo 'Making internal symbolic non-directory links'
|
||||
cd ${INPUT}
|
||||
files=`find . -type l -print`
|
||||
for file in $files; do
|
||||
dest=`ls -ld $file | sed -n 's/.*-> //p'`
|
||||
if expr "$dest" : '[^/].*' > /dev/null; then
|
||||
target=${LIB}/`echo file | sed "s|[^/]*\$|$dest|"`
|
||||
if [ -f $target ]; then
|
||||
ln -s $dest ${LIB}/$file >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
exit 0
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,232 +0,0 @@
|
|||
#! sh
|
||||
#
|
||||
# fixinc.winnt -- Install modified versions of Windows NT system include
|
||||
# files.
|
||||
#
|
||||
# Based on fixinc.sco script by Ian Lance Taylor (ian@airs.com)).
|
||||
# Modifications by Douglas Rupp (drupp@cs.washington.edu)
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# This script munges the native include files provided with Windows NT
|
||||
# 3.5 SDK systems so as to provide a reasonable namespace when
|
||||
# compiling with gcc. The header files by default do not
|
||||
# provide many essential definitions and declarations if
|
||||
# __STDC__ is 1. This script modifies the header files to check
|
||||
# for __STRICT_ANSI__ being defined instead. Once munged, the
|
||||
# resulting new system include files are placed in a directory
|
||||
# that GNU C will search *before* searching the Include
|
||||
# directory.
|
||||
#
|
||||
# See README-fixinc for more information.
|
||||
|
||||
ORIG_DIR=`pwd`
|
||||
|
||||
# Directory containing the original header files.
|
||||
cd $2; SEDFILE=`${PWDCMD-pwd}`/fixinc-nt.sed
|
||||
echo $SEDFILE
|
||||
if [ ! -f $SEDFILE ]
|
||||
then echo fixincludes: sed script 'fixinc-nt.sed' not found
|
||||
exit 1
|
||||
fi
|
||||
echo 'Using sed script: ' ${SEDFILE}
|
||||
|
||||
cd $ORIG_DIR
|
||||
|
||||
INPUT=${INCLUDE}
|
||||
echo 'Using the Include environment variable to find header files to fix'
|
||||
|
||||
# Fail if no arg to specify a directory for the output.
|
||||
if [ x$1 = x ]
|
||||
then echo fixincludes: no output directory specified
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Directory in which to store the results.
|
||||
LIB=${1?"fixincludes: output directory not specified"}
|
||||
|
||||
# Make sure it exists.
|
||||
if [ ! -d $LIB ]; then
|
||||
mkdir $LIB || exit 1
|
||||
fi
|
||||
|
||||
ORIG_DIR=`pwd`
|
||||
|
||||
# Make LIB absolute if it is relative.
|
||||
# Don't do this if not necessary, since may screw up automounters.
|
||||
case $LIB in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
cd $LIB; LIB=`${PWDCMD-pwd}`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo 'Building fixincludes in ' ${LIB}
|
||||
|
||||
# Determine whether this filesystem has symbolic links.
|
||||
if ln -s X $LIB/ShouldNotExist 2>NUL; then
|
||||
rm -f $LIB/ShouldNotExist
|
||||
LINKS=true
|
||||
else
|
||||
LINKS=false
|
||||
fi
|
||||
|
||||
echo 'Making directories:'
|
||||
cd ${INPUT}
|
||||
if $LINKS; then
|
||||
files=`ls -LR | sed -n s/:$//p`
|
||||
else
|
||||
files=`find . -type d -print | sed '/^.$/d'`
|
||||
fi
|
||||
for file in $files; do
|
||||
rm -rf $LIB/$file
|
||||
if [ ! -d $LIB/$file ]
|
||||
then mkdir $LIB/$file
|
||||
fi
|
||||
done
|
||||
|
||||
# treetops gets an alternating list
|
||||
# of old directories to copy
|
||||
# and the new directories to copy to.
|
||||
treetops="${INPUT} ${LIB}"
|
||||
|
||||
set - $treetops
|
||||
while [ $# != 0 ]; do
|
||||
# $1 is an old directory to copy, and $2 is the new directory to copy to.
|
||||
echo "Finding header files in $1:"
|
||||
cd ${INPUT}
|
||||
cd $1
|
||||
files=`find . -name '*.[hH]' -type f -print`
|
||||
echo 'Checking header files:'
|
||||
for file in $files; do
|
||||
echo $file
|
||||
if egrep "!__STDC__" $file >NUL; then
|
||||
if [ -r $file ]; then
|
||||
cp $file $2/$file >NUL 2>&1 || echo "Can't copy $file"
|
||||
chmod +w,a+r $2/$file
|
||||
|
||||
# The following have been removed from the sed command below
|
||||
# because it is more useful to leave these things in.
|
||||
# The only reason to remove them was for -pedantic,
|
||||
# which isn't much of a reason. -- rms.
|
||||
# /^[ ]*#[ ]*ident/d
|
||||
|
||||
sed -e '
|
||||
s/!__STDC__/!defined (__STRICT_ANSI__)/g
|
||||
' $2/$file > $2/$file.sed
|
||||
mv $2/$file.sed $2/$file
|
||||
if cmp $file $2/$file >NUL 2>&1; then
|
||||
rm $2/$file
|
||||
else
|
||||
echo Fixed $file
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
shift; shift
|
||||
done
|
||||
|
||||
# Fix first broken decl of getcwd present on some svr4 systems.
|
||||
|
||||
file=direct.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e 's/getcwd(char \*, int)/getcwd(char *, size_t)/' $file_to_fix > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >NUL 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
file=rpcndr.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e 's/Format\[\]/Format\[1\]/' $file_to_fix > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >NUL 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
file=winnt.h
|
||||
base=`basename $file`
|
||||
if [ -r ${LIB}/$file ]; then
|
||||
file_to_fix=${LIB}/$file
|
||||
else
|
||||
if [ -r ${INPUT}/$file ]; then
|
||||
file_to_fix=${INPUT}/$file
|
||||
else
|
||||
file_to_fix=""
|
||||
fi
|
||||
fi
|
||||
if [ \! -z "$file_to_fix" ]; then
|
||||
echo Checking $file_to_fix
|
||||
sed -e '
|
||||
s/^#if !defined (__cplusplus)/#if 0/
|
||||
s/^#define DECLSPEC_IMPORT __declspec(dllimport)/#define DECLSPEC_IMPORT/
|
||||
' $file_to_fix > /tmp/$base
|
||||
if cmp $file_to_fix /tmp/$base >NUL 2>&1; then \
|
||||
true
|
||||
else
|
||||
echo Fixed $file_to_fix
|
||||
rm -f ${LIB}/$file
|
||||
cp /tmp/$base ${LIB}/$file
|
||||
chmod a+r ${LIB}/$file
|
||||
fi
|
||||
rm -f /tmp/$base
|
||||
fi
|
||||
|
||||
echo 'Removing unneeded directories:'
|
||||
cd $LIB
|
||||
files=`find . -type d -print | sort -r`
|
||||
for file in $files; do
|
||||
rmdir $LIB/$file > NUL 2>&1
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
#
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* Bytecode specific machine mode info for GNU C-compiler.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Map mode to signed, unsigned typecodes, bytecode to push const,
|
||||
to load, to store */
|
||||
DEF_MODEMAP(QImode, QIcode, QUcode, constQI, loadQI, storeQI)
|
||||
DEF_MODEMAP(HImode, HIcode, HUcode, constHI, loadHI, storeHI)
|
||||
DEF_MODEMAP(VOIDmode, SIcode, SUcode, constSI, loadSI, storeSI)
|
||||
DEF_MODEMAP(SImode, SIcode, SUcode, constSI, loadSI, storeSI)
|
||||
DEF_MODEMAP(DImode, DIcode, DUcode, constDI, loadDI, storeDI)
|
||||
DEF_MODEMAP(PSImode, Pcode, Pcode, constP, loadP, storeP)
|
||||
DEF_MODEMAP(BLKmode, Pcode, Pcode, constP, loadP, neverneverland)
|
||||
DEF_MODEMAP(SFmode, SFcode, SFcode, constSF, loadSF, storeSF)
|
||||
DEF_MODEMAP(DFmode, DFcode, DFcode, constDF, loadDF, storeDF)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,117 +0,0 @@
|
|||
/* Declarations for objc-act.c.
|
||||
Copyright (C) 1990 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
/*** Public Interface (procedures) ***/
|
||||
|
||||
/* used by yyparse */
|
||||
|
||||
void finish_file PROTO((void));
|
||||
tree start_class PROTO((enum tree_code, tree, tree, tree));
|
||||
tree continue_class PROTO((tree));
|
||||
void finish_class PROTO((tree));
|
||||
void start_method_def PROTO((tree));
|
||||
void continue_method_def PROTO((void));
|
||||
void finish_method_def PROTO((void));
|
||||
tree start_protocol PROTO((enum tree_code, tree, tree));
|
||||
void finish_protocol PROTO((tree));
|
||||
void add_objc_decls PROTO((void));
|
||||
|
||||
tree is_ivar PROTO((tree, tree));
|
||||
int is_private PROTO((tree));
|
||||
int is_public PROTO((tree, tree));
|
||||
tree add_instance_variable PROTO((tree, int, tree, tree, tree));
|
||||
tree add_class_method PROTO((tree, tree));
|
||||
tree add_instance_method PROTO((tree, tree));
|
||||
tree get_super_receiver PROTO((void));
|
||||
tree get_class_ivars PROTO((tree));
|
||||
tree get_class_reference PROTO((tree));
|
||||
tree get_static_reference PROTO((tree, tree));
|
||||
tree get_object_reference PROTO((tree));
|
||||
tree build_message_expr PROTO((tree));
|
||||
tree build_selector_expr PROTO((tree));
|
||||
tree build_ivar_reference PROTO((tree));
|
||||
tree build_keyword_decl PROTO((tree, tree, tree));
|
||||
tree build_method_decl PROTO((enum tree_code, tree, tree, tree));
|
||||
tree build_protocol_expr PROTO((tree));
|
||||
tree build_objc_string_object PROTO((tree));
|
||||
|
||||
extern tree objc_ivar_chain;
|
||||
extern tree objc_method_context;
|
||||
|
||||
void objc_declare_alias PROTO((tree, tree));
|
||||
void objc_declare_class PROTO((tree));
|
||||
|
||||
extern int objc_receiver_context;
|
||||
|
||||
/* the following routines are used to implement statically typed objects */
|
||||
|
||||
int objc_comptypes PROTO((tree, tree, int));
|
||||
void objc_check_decl PROTO((tree));
|
||||
|
||||
/* NeXT extensions */
|
||||
|
||||
tree build_encode_expr PROTO((tree));
|
||||
|
||||
/* Objective-C structures */
|
||||
|
||||
/* KEYWORD_DECL */
|
||||
#define KEYWORD_KEY_NAME(DECL) ((DECL)->decl.name)
|
||||
#define KEYWORD_ARG_NAME(DECL) ((DECL)->decl.arguments)
|
||||
|
||||
/* INSTANCE_METHOD_DECL, CLASS_METHOD_DECL */
|
||||
#define METHOD_SEL_NAME(DECL) ((DECL)->decl.name)
|
||||
#define METHOD_SEL_ARGS(DECL) ((DECL)->decl.arguments)
|
||||
#define METHOD_ADD_ARGS(DECL) ((DECL)->decl.result)
|
||||
#define METHOD_DEFINITION(DECL) ((DECL)->decl.initial)
|
||||
#define METHOD_ENCODING(DECL) ((DECL)->decl.context)
|
||||
|
||||
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
|
||||
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
|
||||
PROTOCOL_INTERFACE_TYPE */
|
||||
#define CLASS_NAME(CLASS) ((CLASS)->type.name)
|
||||
#define CLASS_SUPER_NAME(CLASS) ((CLASS)->type.context)
|
||||
#define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 0)
|
||||
#define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1)
|
||||
#define CLASS_NST_METHODS(CLASS) ((CLASS)->type.minval)
|
||||
#define CLASS_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
|
||||
#define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 2)
|
||||
#define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 3)
|
||||
#define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 4)
|
||||
#define PROTOCOL_NAME(CLASS) ((CLASS)->type.name)
|
||||
#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 0)
|
||||
#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
|
||||
#define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
|
||||
#define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1)
|
||||
#define TYPE_PROTOCOL_LIST(TYPE) ((TYPE)->type.context)
|
||||
|
||||
/* Define the Objective-C or Objective-C++ language-specific tree codes. */
|
||||
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
|
||||
enum objc_tree_code {
|
||||
#ifdef OBJCPLUS
|
||||
dummy_tree_code = LAST_CPLUS_TREE_CODE,
|
||||
#else
|
||||
dummy_tree_code = LAST_AND_UNUSED_TREE_CODE,
|
||||
#endif
|
||||
#include "objc-tree.def"
|
||||
LAST_OBJC_TREE_CODE
|
||||
};
|
||||
#undef DEFTREECODE
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/* This file contains the definitions and documentation for the
|
||||
additional tree codes used in the Objective C front end (see tree.def
|
||||
for the standard codes).
|
||||
Copyright (C) 1990 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
/* Objective-C types. */
|
||||
DEFTREECODE (CLASS_INTERFACE_TYPE, "class_interface_type", "t", 0)
|
||||
DEFTREECODE (CLASS_IMPLEMENTATION_TYPE, "class_implementation_type", "t", 0)
|
||||
DEFTREECODE (CATEGORY_INTERFACE_TYPE, "category_interface_type", "t", 0)
|
||||
DEFTREECODE (CATEGORY_IMPLEMENTATION_TYPE,"category_implementation_type","t",0)
|
||||
DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", "t", 0)
|
||||
|
||||
/* Objective-C decls. */
|
||||
DEFTREECODE (KEYWORD_DECL, "keyword_decl", "d", 0)
|
||||
DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", "d", 0)
|
||||
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", "d", 0)
|
||||
|
||||
/* Objective-C constants. */
|
||||
DEFTREECODE (OBJC_STRING_CST, "objc_string_cst", "c", 3)
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# GNU Objective C Runtime Makefile
|
||||
# Copyright (C) 1993, 1995 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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
|
||||
# GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
# Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# This makefile is run by the parent dir's makefile.
|
||||
# thisdir1=`pwd`; \
|
||||
# srcdir1=`cd $(srcdir); pwd`; \
|
||||
# cd objc; \
|
||||
# $(MAKE) $(MAKEFLAGS) -f $$srcdir1/objc/Makefile libobjc.a \
|
||||
# srcdir=$$srcdir1 tooldir=$(tooldir) AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \
|
||||
# GCC_FOR_TARGET="$$thisdir1/xgcc -B$$thisdir1/" \
|
||||
# GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=$$thisdir1/include
|
||||
# Two targets are used by ../Makefile: `all' and `mostlyclean'.
|
||||
|
||||
SHELL=/bin/sh
|
||||
|
||||
.SUFFIXES: .m
|
||||
|
||||
OPTIMIZE= -O
|
||||
|
||||
VPATH = $(srcdir)/objc
|
||||
|
||||
AR = ar
|
||||
AR_FLAGS = rc
|
||||
|
||||
# Always search these dirs when compiling.
|
||||
SUBDIR_INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/config
|
||||
|
||||
.c.o:
|
||||
$(GCC_FOR_TARGET) $(OPTIMIZE) \
|
||||
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
|
||||
|
||||
.m.o:
|
||||
$(GCC_FOR_TARGET) $(OPTIMIZE) -fgnu-runtime \
|
||||
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
|
||||
|
||||
# If we were not invoked from the parent dir,
|
||||
# invoke make in the parent dir and have reinvoke this makefile.
|
||||
# That's necessary to get the right values for srcdir, etc.
|
||||
all:
|
||||
cd ..; $(MAKE) sublibobjc.a
|
||||
|
||||
OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o encoding.o \
|
||||
selector.o objects.o misc.o NXConstStr.o Object.o Protocol.o
|
||||
|
||||
libobjc.a: $(OBJC_O)
|
||||
-rm -f libobjc.a
|
||||
$(AR) rc libobjc.a $?
|
||||
# ranlib is run in the parent directory's makefile.
|
||||
|
||||
OBJC_H = hash.h list.h sarray.h objc.h \
|
||||
objc-api.h \
|
||||
NXConstStr.h Object.h Protocol.h encoding.h typedstream.h
|
||||
|
||||
# copy objc headers to installation include directory
|
||||
copy-headers:
|
||||
-rm -fr $(incinstalldir)/objc
|
||||
-mkdir $(incinstalldir)/objc
|
||||
for file in $(OBJC_H); do \
|
||||
realfile=$(srcdir)/objc/$${file}; \
|
||||
cp $${realfile} $(incinstalldir)/objc; \
|
||||
chmod a+r $(incinstalldir)/objc/$${file}; \
|
||||
done
|
||||
|
||||
mostlyclean:
|
||||
-rm -f *.o libobjc.a xforward fflags
|
||||
clean: mostlyclean
|
||||
distclean: mostlyclean
|
||||
extraclean: mostlyclean
|
||||
|
||||
# For Sun VPATH.
|
||||
|
||||
hash.o: hash.c
|
||||
sarray.o: sarray.c
|
||||
class.o: class.c
|
||||
sendmsg.o: sendmsg.c
|
||||
init.o: init.c
|
||||
archive.o: archive.c
|
||||
encoding.o: encoding.c
|
||||
selector.o: selector.c
|
||||
objects.o: objects.c
|
||||
misc.o: misc.c
|
||||
NXConstStr.o: NXConstStr.m
|
||||
Object.o: Object.m
|
||||
Protocol.o: Protocol.m
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/* Interface for the NXConstantString class for Objective-C.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Contributed by Pieter J. Schoenmakers <tiggr@es.ele.tue.nl>
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __nxconstantstring_INCLUDE_GNU
|
||||
#define __nxconstantstring_INCLUDE_GNU
|
||||
|
||||
#include "objc/Object.h"
|
||||
|
||||
@interface NXConstantString: Object
|
||||
{
|
||||
char *c_string;
|
||||
unsigned int len;
|
||||
}
|
||||
|
||||
-(const char *) cString;
|
||||
-(unsigned int) length;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* Implementation of the NXConstantString class for Objective-C.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Contributed by Pieter J. Schoenmakers <tiggr@es.ele.tue.nl>
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include "objc/NXConstStr.h"
|
||||
|
||||
@implementation NXConstantString
|
||||
|
||||
-(const char *) cString
|
||||
{
|
||||
return (c_string);
|
||||
} /* -cString */
|
||||
|
||||
-(unsigned int) length
|
||||
{
|
||||
return (len);
|
||||
} /* -length */
|
||||
|
||||
@end
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
/* Interface for the Object class for Objective-C.
|
||||
Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled
|
||||
with GCC to produce an executable, this does not cause the resulting
|
||||
executable to be covered by the GNU General Public License. This
|
||||
exception does not however invalidate any other reasons why the
|
||||
executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __object_INCLUDE_GNU
|
||||
#define __object_INCLUDE_GNU
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <objc/typedstream.h>
|
||||
|
||||
/*
|
||||
* All classes are derived from Object. As such,
|
||||
* this is the overhead tacked onto those objects.
|
||||
*/
|
||||
@interface Object
|
||||
{
|
||||
Class isa; /* A pointer to the instance's class structure */
|
||||
}
|
||||
|
||||
/* Initializing classes and instances */
|
||||
+ initialize;
|
||||
- init;
|
||||
|
||||
/* Creating, freeing, and copying instances */
|
||||
+ new;
|
||||
+ alloc;
|
||||
- free;
|
||||
- copy;
|
||||
- shallowCopy;
|
||||
- deepen;
|
||||
- deepCopy;
|
||||
|
||||
/* Identifying classes */
|
||||
- (Class)class;
|
||||
- (Class)superClass;
|
||||
- (MetaClass)metaClass;
|
||||
- (const char *)name;
|
||||
|
||||
/* Identifying and comparing objects */
|
||||
- self;
|
||||
- (unsigned int)hash;
|
||||
- (BOOL)isEqual:anObject;
|
||||
- (int)compare:anotherObject;
|
||||
|
||||
/* Testing object type */
|
||||
- (BOOL)isMetaClass;
|
||||
- (BOOL)isClass;
|
||||
- (BOOL)isInstance;
|
||||
|
||||
/* Testing inheritance relationships */
|
||||
- (BOOL)isKindOf:(Class)aClassObject;
|
||||
- (BOOL)isMemberOf:(Class)aClassObject;
|
||||
- (BOOL)isKindOfClassNamed:(const char *)aClassName;
|
||||
- (BOOL)isMemberOfClassNamed:(const char *)aClassName;
|
||||
|
||||
/* Testing class functionality */
|
||||
+ (BOOL)instancesRespondTo:(SEL)aSel;
|
||||
- (BOOL)respondsTo:(SEL)aSel;
|
||||
|
||||
/* Testing protocol conformance */
|
||||
- (BOOL)conformsTo:(Protocol*)aProtocol;
|
||||
|
||||
/* Introspection */
|
||||
+ (IMP)instanceMethodFor:(SEL)aSel;
|
||||
- (IMP)methodFor:(SEL)aSel;
|
||||
+ (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel;
|
||||
- (struct objc_method_description *)descriptionForMethod:(SEL)aSel;
|
||||
|
||||
/* Sending messages determined at run time */
|
||||
- perform:(SEL)aSel;
|
||||
- perform:(SEL)aSel with:anObject;
|
||||
- perform:(SEL)aSel with:anObject1 with:anObject2;
|
||||
|
||||
/* Forwarding */
|
||||
- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
|
||||
- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
|
||||
|
||||
/* Posing */
|
||||
+ poseAs:(Class)aClassObject;
|
||||
- (Class)transmuteClassTo:(Class)aClassObject;
|
||||
|
||||
/* Enforcing intentions */
|
||||
- subclassResponsibility:(SEL)aSel;
|
||||
- notImplemented:(SEL)aSel;
|
||||
- shouldNotImplement:(SEL)aSel;
|
||||
|
||||
/* Error handling */
|
||||
- doesNotRecognize:(SEL)aSel;
|
||||
- error:(const char *)aString, ...;
|
||||
|
||||
/* Archiving */
|
||||
+ (int)version;
|
||||
+ setVersion:(int)aVersion;
|
||||
+ (int)streamVersion: (TypedStream*)aStream;
|
||||
|
||||
- read: (TypedStream*)aStream;
|
||||
- write: (TypedStream*)aStream;
|
||||
- awake;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
@ -1,387 +0,0 @@
|
|||
/* The implementation of class Object for Objective-C.
|
||||
Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled
|
||||
with GCC to produce an executable, this does not cause the resulting
|
||||
executable to be covered by the GNU General Public License. This
|
||||
exception does not however invalidate any other reasons why the
|
||||
executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "objc/Object.h"
|
||||
#include "objc/Protocol.h"
|
||||
#include "objc/objc-api.h"
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define MAX_CLASS_NAME_LEN 256
|
||||
|
||||
@implementation Object
|
||||
|
||||
+ initialize
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
+ new
|
||||
{
|
||||
return [[self alloc] init];
|
||||
}
|
||||
|
||||
+ alloc
|
||||
{
|
||||
return class_create_instance(self);
|
||||
}
|
||||
|
||||
- free
|
||||
{
|
||||
return object_dispose(self);
|
||||
}
|
||||
|
||||
- copy
|
||||
{
|
||||
return [[self shallowCopy] deepen];
|
||||
}
|
||||
|
||||
- shallowCopy
|
||||
{
|
||||
return object_copy(self);
|
||||
}
|
||||
|
||||
- deepen
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- deepCopy
|
||||
{
|
||||
return [self copy];
|
||||
}
|
||||
|
||||
- (Class)class
|
||||
{
|
||||
return object_get_class(self);
|
||||
}
|
||||
|
||||
- (Class)superClass
|
||||
{
|
||||
return object_get_super_class(self);
|
||||
}
|
||||
|
||||
- (MetaClass)metaClass
|
||||
{
|
||||
return object_get_meta_class(self);
|
||||
}
|
||||
|
||||
- (const char *)name
|
||||
{
|
||||
return object_get_class_name(self);
|
||||
}
|
||||
|
||||
- self
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned int)hash
|
||||
{
|
||||
return (size_t)self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:anObject
|
||||
{
|
||||
return self==anObject;
|
||||
}
|
||||
|
||||
- (int)compare:anotherObject;
|
||||
{
|
||||
if ([self isEqual:anotherObject])
|
||||
return 0;
|
||||
// Ordering objects by their address is pretty useless,
|
||||
// so subclasses should override this is some useful way.
|
||||
else if (self > anotherObject)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (BOOL)isMetaClass
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isClass
|
||||
{
|
||||
return object_is_class(self);
|
||||
}
|
||||
|
||||
- (BOOL)isInstance
|
||||
{
|
||||
return object_is_instance(self);
|
||||
}
|
||||
|
||||
- (BOOL)isKindOf:(Class)aClassObject
|
||||
{
|
||||
Class class;
|
||||
|
||||
for (class = self->isa; class!=Nil; class = class_get_super_class(class))
|
||||
if (class==aClassObject)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isMemberOf:(Class)aClassObject
|
||||
{
|
||||
return self->isa==aClassObject;
|
||||
}
|
||||
|
||||
- (BOOL)isKindOfClassNamed:(const char *)aClassName
|
||||
{
|
||||
Class class;
|
||||
|
||||
if (aClassName!=NULL)
|
||||
for (class = self->isa; class!=Nil; class = class_get_super_class(class))
|
||||
if (!strcmp(class_get_class_name(class), aClassName))
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isMemberOfClassNamed:(const char *)aClassName
|
||||
{
|
||||
return ((aClassName!=NULL)
|
||||
&&!strcmp(class_get_class_name(self->isa), aClassName));
|
||||
}
|
||||
|
||||
+ (BOOL)instancesRespondTo:(SEL)aSel
|
||||
{
|
||||
return class_get_instance_method(self, aSel)!=METHOD_NULL;
|
||||
}
|
||||
|
||||
- (BOOL)respondsTo:(SEL)aSel
|
||||
{
|
||||
return ((object_is_instance(self)
|
||||
?class_get_instance_method(self->isa, aSel)
|
||||
:class_get_class_method(self->isa, aSel))!=METHOD_NULL);
|
||||
}
|
||||
|
||||
+ (IMP)instanceMethodFor:(SEL)aSel
|
||||
{
|
||||
return method_get_imp(class_get_instance_method(self, aSel));
|
||||
}
|
||||
|
||||
// Indicates if the receiving class or instance conforms to the given protocol
|
||||
// not usually overridden by subclasses
|
||||
//
|
||||
// Modified 9/5/94 to always search the class object's protocol list, rather
|
||||
// than the meta class.
|
||||
|
||||
+ (BOOL) conformsTo: (Protocol*)aProtocol
|
||||
{
|
||||
int i;
|
||||
struct objc_protocol_list* proto_list;
|
||||
id parent;
|
||||
|
||||
for (proto_list = ((Class)self)->protocols;
|
||||
proto_list; proto_list = proto_list->next)
|
||||
{
|
||||
for (i=0; i < proto_list->count; i++)
|
||||
{
|
||||
if ([proto_list->list[i] conformsTo: aProtocol])
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
if ((parent = [self superClass]))
|
||||
return [parent conformsTo: aProtocol];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) conformsTo: (Protocol*)aProtocol
|
||||
{
|
||||
return [[self class] conformsTo:aProtocol];
|
||||
}
|
||||
|
||||
- (IMP)methodFor:(SEL)aSel
|
||||
{
|
||||
return (method_get_imp(object_is_instance(self)
|
||||
?class_get_instance_method(self->isa, aSel)
|
||||
:class_get_class_method(self->isa, aSel)));
|
||||
}
|
||||
|
||||
+ (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel
|
||||
{
|
||||
return ((struct objc_method_description *)
|
||||
class_get_instance_method(self, aSel));
|
||||
}
|
||||
|
||||
- (struct objc_method_description *)descriptionForMethod:(SEL)aSel
|
||||
{
|
||||
return ((struct objc_method_description *)
|
||||
(object_is_instance(self)
|
||||
?class_get_instance_method(self->isa, aSel)
|
||||
:class_get_class_method(self->isa, aSel)));
|
||||
}
|
||||
|
||||
- perform:(SEL)aSel
|
||||
{
|
||||
IMP msg = objc_msg_lookup(self, aSel);
|
||||
if (!msg)
|
||||
return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
|
||||
return (*msg)(self, aSel);
|
||||
}
|
||||
|
||||
- perform:(SEL)aSel with:anObject
|
||||
{
|
||||
IMP msg = objc_msg_lookup(self, aSel);
|
||||
if (!msg)
|
||||
return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
|
||||
return (*msg)(self, aSel, anObject);
|
||||
}
|
||||
|
||||
- perform:(SEL)aSel with:anObject1 with:anObject2
|
||||
{
|
||||
IMP msg = objc_msg_lookup(self, aSel);
|
||||
if (!msg)
|
||||
return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
|
||||
return (*msg)(self, aSel, anObject1, anObject2);
|
||||
}
|
||||
|
||||
- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame
|
||||
{
|
||||
return (retval_t)[self doesNotRecognize: aSel];
|
||||
}
|
||||
|
||||
- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame
|
||||
{
|
||||
return objc_msg_sendv(self, aSel, argFrame);
|
||||
}
|
||||
|
||||
+ poseAs:(Class)aClassObject
|
||||
{
|
||||
return class_pose_as(self, aClassObject);
|
||||
}
|
||||
|
||||
- (Class)transmuteClassTo:(Class)aClassObject
|
||||
{
|
||||
if (object_is_instance(self))
|
||||
if (class_is_class(aClassObject))
|
||||
if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
|
||||
if ([self isKindOf:aClassObject])
|
||||
{
|
||||
Class old_isa = isa;
|
||||
isa = aClassObject;
|
||||
return old_isa;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- subclassResponsibility:(SEL)aSel
|
||||
{
|
||||
return [self error:"subclass should override %s", sel_get_name(aSel)];
|
||||
}
|
||||
|
||||
- notImplemented:(SEL)aSel
|
||||
{
|
||||
return [self error:"method %s not implemented", sel_get_name(aSel)];
|
||||
}
|
||||
|
||||
- shouldNotImplement:(SEL)aSel
|
||||
{
|
||||
return [self error:"%s should not implement %s",
|
||||
object_get_class_name(self), sel_get_name(aSel)];
|
||||
}
|
||||
|
||||
- doesNotRecognize:(SEL)aSel
|
||||
{
|
||||
return [self error:"%s does not recognize %s",
|
||||
object_get_class_name(self), sel_get_name(aSel)];
|
||||
}
|
||||
|
||||
#ifdef __alpha__
|
||||
extern size_t strlen(const char*);
|
||||
#endif
|
||||
|
||||
- error:(const char *)aString, ...
|
||||
{
|
||||
#define FMT "error: %s (%s)\n%s\n"
|
||||
char fmt[(strlen((char*)FMT)+strlen((char*)object_get_class_name(self))
|
||||
+((aString!=NULL)?strlen((char*)aString):0)+8)];
|
||||
va_list ap;
|
||||
|
||||
sprintf(fmt, FMT, object_get_class_name(self),
|
||||
object_is_instance(self)?"instance":"class",
|
||||
(aString!=NULL)?aString:"");
|
||||
va_start(ap, aString);
|
||||
objc_verror(self, OBJC_ERR_UNKNOWN, fmt, ap);
|
||||
va_end(ap);
|
||||
return nil;
|
||||
#undef FMT
|
||||
}
|
||||
|
||||
+ (int)version
|
||||
{
|
||||
return class_get_version(self);
|
||||
}
|
||||
|
||||
+ setVersion:(int)aVersion
|
||||
{
|
||||
class_set_version(self, aVersion);
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (int)streamVersion: (TypedStream*)aStream
|
||||
{
|
||||
if (aStream->mode == OBJC_READONLY)
|
||||
return objc_get_stream_class_version (aStream, self);
|
||||
else
|
||||
return class_get_version (self);
|
||||
}
|
||||
|
||||
// These are used to write or read the instance variables
|
||||
// declared in this particular part of the object. Subclasses
|
||||
// should extend these, by calling [super read/write: aStream]
|
||||
// before doing their own archiving. These methods are private, in
|
||||
// the sense that they should only be called from subclasses.
|
||||
|
||||
- read: (TypedStream*)aStream
|
||||
{
|
||||
// [super read: aStream];
|
||||
return self;
|
||||
}
|
||||
|
||||
- write: (TypedStream*)aStream
|
||||
{
|
||||
// [super write: aStream];
|
||||
return self;
|
||||
}
|
||||
|
||||
- awake
|
||||
{
|
||||
// [super awake];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/* Declare the class Protocol for Objective C programs.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __Protocol_INCLUDE_GNU
|
||||
#define __Protocol_INCLUDE_GNU
|
||||
|
||||
#include "objc/Object.h"
|
||||
|
||||
@interface Protocol : Object
|
||||
{
|
||||
@private
|
||||
char *protocol_name;
|
||||
struct objc_protocol_list *protocol_list;
|
||||
struct objc_method_description_list *instance_methods, *class_methods;
|
||||
}
|
||||
|
||||
/* Obtaining attributes intrinsic to the protocol */
|
||||
|
||||
- (const char *)name;
|
||||
|
||||
/* Testing protocol conformance */
|
||||
|
||||
- (BOOL) conformsTo: (Protocol *)aProtocolObject;
|
||||
|
||||
/* Looking up information specific to a protocol */
|
||||
|
||||
- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel;
|
||||
- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
#endif __Protocol_INCLUDE_GNU
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
/* This file contains the implementation of class Protocol.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include "objc/Protocol.h"
|
||||
#include "objc/objc-api.h"
|
||||
|
||||
/* Method description list */
|
||||
struct objc_method_description_list {
|
||||
int count;
|
||||
struct objc_method_description list[1];
|
||||
};
|
||||
|
||||
|
||||
@implementation Protocol
|
||||
{
|
||||
@private
|
||||
char *protocol_name;
|
||||
struct objc_protocol_list *protocol_list;
|
||||
struct objc_method_description_list *instance_methods, *class_methods;
|
||||
}
|
||||
|
||||
/* Obtaining attributes intrinsic to the protocol */
|
||||
|
||||
- (const char *)name
|
||||
{
|
||||
return protocol_name;
|
||||
}
|
||||
|
||||
/* Testing protocol conformance */
|
||||
|
||||
- (BOOL) conformsTo: (Protocol *)aProtocolObject
|
||||
{
|
||||
int i;
|
||||
struct objc_protocol_list* proto_list;
|
||||
|
||||
if (!strcmp(aProtocolObject->protocol_name, self->protocol_name))
|
||||
return YES;
|
||||
|
||||
for (proto_list = protocol_list; proto_list; proto_list = proto_list->next)
|
||||
{
|
||||
for (i=0; i < proto_list->count; i++)
|
||||
{
|
||||
if ([proto_list->list[i] conformsTo: aProtocolObject])
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Looking up information specific to a protocol */
|
||||
|
||||
- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel
|
||||
{
|
||||
int i;
|
||||
struct objc_protocol_list* proto_list;
|
||||
const char* name = sel_get_name (aSel);
|
||||
struct objc_method_description *result;
|
||||
|
||||
for (i = 0; i < instance_methods->count; i++)
|
||||
{
|
||||
if (!strcmp ((char*)instance_methods->list[i].name, name))
|
||||
return &(instance_methods->list[i]);
|
||||
}
|
||||
|
||||
for (proto_list = protocol_list; proto_list; proto_list = proto_list->next)
|
||||
{
|
||||
for (i=0; i < proto_list->count; i++)
|
||||
{
|
||||
if ((result = [proto_list->list[i]
|
||||
descriptionForInstanceMethod: aSel]))
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel;
|
||||
{
|
||||
int i;
|
||||
struct objc_protocol_list* proto_list;
|
||||
const char* name = sel_get_name (aSel);
|
||||
struct objc_method_description *result;
|
||||
|
||||
for (i = 0; i < class_methods->count; i++)
|
||||
{
|
||||
if (!strcmp ((char*)class_methods->list[i].name, name))
|
||||
return &(class_methods->list[i]);
|
||||
}
|
||||
|
||||
for (proto_list = protocol_list; proto_list; proto_list = proto_list->next)
|
||||
{
|
||||
for (i=0; i < proto_list->count; i++)
|
||||
{
|
||||
if ((result = [proto_list->list[i]
|
||||
descriptionForClassMethod: aSel]))
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,358 +0,0 @@
|
|||
/* GNU Objective C Runtime class related functions
|
||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup and Dennis Glatting.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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
|
||||
GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#include "runtime.h" /* the kitchen sink */
|
||||
#include "sarray.h"
|
||||
|
||||
/* The table of classname->class. Used for objc_lookup_class and friends */
|
||||
static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */
|
||||
|
||||
/* This is a hook which is called by objc_get_class and
|
||||
objc_lookup_class if the runtime is not able to find the class.
|
||||
This may e.g. try to load in the class using dynamic loading */
|
||||
Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
|
||||
|
||||
|
||||
/* True when class links has been resolved */
|
||||
BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
|
||||
|
||||
|
||||
/* Initial number of buckets size of class hash table. */
|
||||
#define CLASS_HASH_SIZE 32
|
||||
|
||||
void __objc_init_class_tables()
|
||||
{
|
||||
/* Allocate the class hash table */
|
||||
|
||||
if(__objc_class_hash)
|
||||
return;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
__objc_class_hash
|
||||
= hash_new (CLASS_HASH_SIZE,
|
||||
(hash_func_type) hash_string,
|
||||
(compare_func_type) compare_strings);
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* This function adds a class to the class hash table, and assigns the
|
||||
class a number, unless it's already known */
|
||||
void
|
||||
__objc_add_class_to_hash(Class class)
|
||||
{
|
||||
Class h_class;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
/* make sure the table is there */
|
||||
assert(__objc_class_hash);
|
||||
|
||||
/* make sure it's not a meta class */
|
||||
assert(CLS_ISCLASS(class));
|
||||
|
||||
/* Check to see if the class is already in the hash table. */
|
||||
h_class = hash_value_for_key (__objc_class_hash, class->name);
|
||||
if (!h_class)
|
||||
{
|
||||
/* The class isn't in the hash table. Add the class and assign a class
|
||||
number. */
|
||||
static unsigned int class_number = 1;
|
||||
|
||||
CLS_SETNUMBER(class, class_number);
|
||||
CLS_SETNUMBER(class->class_pointer, class_number);
|
||||
|
||||
++class_number;
|
||||
hash_add (&__objc_class_hash, class->name, class);
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* Get the class object for the class named NAME. If NAME does not
|
||||
identify a known class, the hook _objc_lookup_class is called. If
|
||||
this fails, nil is returned */
|
||||
Class objc_lookup_class (const char* name)
|
||||
{
|
||||
Class class;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
/* Make sure the class hash table exists. */
|
||||
assert (__objc_class_hash);
|
||||
|
||||
class = hash_value_for_key (__objc_class_hash, name);
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
if (class)
|
||||
return class;
|
||||
|
||||
if (_objc_lookup_class)
|
||||
return (*_objc_lookup_class)(name);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the class object for the class named NAME. If NAME does not
|
||||
identify a known class, the hook _objc_lookup_class is called. If
|
||||
this fails, an error message is issued and the system aborts */
|
||||
Class
|
||||
objc_get_class (const char *name)
|
||||
{
|
||||
Class class;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
/* Make sure the class hash table exists. */
|
||||
assert (__objc_class_hash);
|
||||
|
||||
class = hash_value_for_key (__objc_class_hash, name);
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
if (class)
|
||||
return class;
|
||||
|
||||
if (_objc_lookup_class)
|
||||
class = (*_objc_lookup_class)(name);
|
||||
|
||||
if(class)
|
||||
return class;
|
||||
|
||||
objc_error(nil, OBJC_ERR_BAD_CLASS,
|
||||
"objc runtime: cannot find class %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MetaClass
|
||||
objc_get_meta_class(const char *name)
|
||||
{
|
||||
return objc_get_class(name)->class_pointer;
|
||||
}
|
||||
|
||||
/* This function provides a way to enumerate all the classes in the
|
||||
executable. Pass *ENUM_STATE == NULL to start the enumeration. The
|
||||
function will return 0 when there are no more classes.
|
||||
For example:
|
||||
id class;
|
||||
void *es = NULL;
|
||||
while ((class = objc_next_class(&es)))
|
||||
... do something with class;
|
||||
*/
|
||||
Class
|
||||
objc_next_class(void **enum_state)
|
||||
{
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
/* make sure the table is there */
|
||||
assert(__objc_class_hash);
|
||||
|
||||
*(node_ptr*)enum_state =
|
||||
hash_next(__objc_class_hash, *(node_ptr*)enum_state);
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
if (*(node_ptr*)enum_state)
|
||||
return (*(node_ptr*)enum_state)->value;
|
||||
return (Class)0;
|
||||
}
|
||||
|
||||
/* Resolve super/subclass links for all classes. The only thing we
|
||||
can be sure of is that the class_pointer for class objects point
|
||||
to the right meta class objects */
|
||||
void __objc_resolve_class_links()
|
||||
{
|
||||
node_ptr node;
|
||||
Class object_class = objc_get_class ("Object");
|
||||
|
||||
assert(object_class);
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
/* Assign subclass links */
|
||||
for (node = hash_next (__objc_class_hash, NULL); node;
|
||||
node = hash_next (__objc_class_hash, node))
|
||||
{
|
||||
Class class1 = node->value;
|
||||
|
||||
/* Make sure we have what we think we have. */
|
||||
assert (CLS_ISCLASS(class1));
|
||||
assert (CLS_ISMETA(class1->class_pointer));
|
||||
|
||||
/* The class_pointer of all meta classes point to Object's meta class. */
|
||||
class1->class_pointer->class_pointer = object_class->class_pointer;
|
||||
|
||||
if (!(CLS_ISRESOLV(class1)))
|
||||
{
|
||||
CLS_SETRESOLV(class1);
|
||||
CLS_SETRESOLV(class1->class_pointer);
|
||||
|
||||
if(class1->super_class)
|
||||
{
|
||||
Class a_super_class
|
||||
= objc_get_class ((char *) class1->super_class);
|
||||
|
||||
assert (a_super_class);
|
||||
|
||||
DEBUG_PRINTF ("making class connections for: %s\n",
|
||||
class1->name);
|
||||
|
||||
/* assign subclass links for superclass */
|
||||
class1->sibling_class = a_super_class->subclass_list;
|
||||
a_super_class->subclass_list = class1;
|
||||
|
||||
/* Assign subclass links for meta class of superclass */
|
||||
if (a_super_class->class_pointer)
|
||||
{
|
||||
class1->class_pointer->sibling_class
|
||||
= a_super_class->class_pointer->subclass_list;
|
||||
a_super_class->class_pointer->subclass_list
|
||||
= class1->class_pointer;
|
||||
}
|
||||
}
|
||||
else /* a root class, make its meta object */
|
||||
/* be a subclass of Object */
|
||||
{
|
||||
class1->class_pointer->sibling_class
|
||||
= object_class->subclass_list;
|
||||
object_class->subclass_list = class1->class_pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign superclass links */
|
||||
for (node = hash_next (__objc_class_hash, NULL); node;
|
||||
node = hash_next (__objc_class_hash, node))
|
||||
{
|
||||
Class class1 = node->value;
|
||||
Class sub_class;
|
||||
for (sub_class = class1->subclass_list; sub_class;
|
||||
sub_class = sub_class->sibling_class)
|
||||
{
|
||||
sub_class->super_class = class1;
|
||||
if(CLS_ISCLASS(sub_class))
|
||||
sub_class->class_pointer->super_class = class1->class_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CLASSOF(c) ((c)->class_pointer)
|
||||
|
||||
Class
|
||||
class_pose_as (Class impostor, Class super_class)
|
||||
{
|
||||
node_ptr node;
|
||||
Class class1;
|
||||
|
||||
if (!CLS_ISRESOLV (impostor))
|
||||
__objc_resolve_class_links ();
|
||||
|
||||
/* preconditions */
|
||||
assert (impostor);
|
||||
assert (super_class);
|
||||
assert (impostor->super_class == super_class);
|
||||
assert (CLS_ISCLASS (impostor));
|
||||
assert (CLS_ISCLASS (super_class));
|
||||
assert (impostor->instance_size == super_class->instance_size);
|
||||
|
||||
{
|
||||
Class *subclass = &(super_class->subclass_list);
|
||||
|
||||
/* move subclasses of super_class to impostor */
|
||||
while (*subclass)
|
||||
{
|
||||
Class nextSub = (*subclass)->sibling_class;
|
||||
|
||||
if (*subclass != impostor)
|
||||
{
|
||||
Class sub = *subclass;
|
||||
|
||||
/* classes */
|
||||
sub->sibling_class = impostor->subclass_list;
|
||||
sub->super_class = impostor;
|
||||
impostor->subclass_list = sub;
|
||||
|
||||
/* It will happen that SUB is not a class object if it is
|
||||
the top of the meta class hierarchy chain. (root
|
||||
meta-class objects inherit their class object) If that is
|
||||
the case... don't mess with the meta-meta class. */
|
||||
if (CLS_ISCLASS (sub))
|
||||
{
|
||||
/* meta classes */
|
||||
CLASSOF (sub)->sibling_class =
|
||||
CLASSOF (impostor)->subclass_list;
|
||||
CLASSOF (sub)->super_class = CLASSOF (impostor);
|
||||
CLASSOF (impostor)->subclass_list = CLASSOF (sub);
|
||||
}
|
||||
}
|
||||
|
||||
*subclass = nextSub;
|
||||
}
|
||||
|
||||
/* set subclasses of superclass to be impostor only */
|
||||
super_class->subclass_list = impostor;
|
||||
CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
|
||||
|
||||
/* set impostor to have no sibling classes */
|
||||
impostor->sibling_class = 0;
|
||||
CLASSOF (impostor)->sibling_class = 0;
|
||||
}
|
||||
|
||||
/* check relationship of impostor and super_class is kept. */
|
||||
assert (impostor->super_class == super_class);
|
||||
assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
|
||||
|
||||
/* This is how to update the lookup table. Regardless of
|
||||
what the keys of the hashtable is, change all values that are
|
||||
superclass into impostor. */
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
for (node = hash_next (__objc_class_hash, NULL); node;
|
||||
node = hash_next (__objc_class_hash, node))
|
||||
{
|
||||
class1 = (Class)node->value;
|
||||
if (class1 == super_class)
|
||||
{
|
||||
node->value = impostor; /* change hash table value */
|
||||
}
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
/* next, we update the dispatch tables... */
|
||||
__objc_update_dispatch_table_for_class (CLASSOF (impostor));
|
||||
__objc_update_dispatch_table_for_class (impostor);
|
||||
|
||||
return impostor;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,554 +0,0 @@
|
|||
/* Encoding of types for Objective C.
|
||||
Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#define MAX(X, Y) \
|
||||
({ typeof(X) __x = (X), __y = (Y); \
|
||||
(__x > __y ? __x : __y); })
|
||||
|
||||
#define MIN(X, Y) \
|
||||
({ typeof(X) __x = (X), __y = (Y); \
|
||||
(__x < __y ? __x : __y); })
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
|
||||
static inline int
|
||||
atoi (const char* str)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
while (isdigit (*str))
|
||||
res *= 10, res += (*str++ - '0');
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
return the size of an object specified by type
|
||||
*/
|
||||
|
||||
int
|
||||
objc_sizeof_type(const char* type)
|
||||
{
|
||||
switch(*type) {
|
||||
case _C_ID:
|
||||
return sizeof(id);
|
||||
break;
|
||||
|
||||
case _C_CLASS:
|
||||
return sizeof(Class);
|
||||
break;
|
||||
|
||||
case _C_SEL:
|
||||
return sizeof(SEL);
|
||||
break;
|
||||
|
||||
case _C_CHR:
|
||||
return sizeof(char);
|
||||
break;
|
||||
|
||||
case _C_UCHR:
|
||||
return sizeof(unsigned char);
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
return sizeof(short);
|
||||
break;
|
||||
|
||||
case _C_USHT:
|
||||
return sizeof(unsigned short);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
return sizeof(int);
|
||||
break;
|
||||
|
||||
case _C_UINT:
|
||||
return sizeof(unsigned int);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
return sizeof(long);
|
||||
break;
|
||||
|
||||
case _C_ULNG:
|
||||
return sizeof(unsigned long);
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
return sizeof(float);
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
return sizeof(double);
|
||||
break;
|
||||
|
||||
case _C_VOID:
|
||||
return sizeof(void);
|
||||
break;
|
||||
case _C_PTR:
|
||||
case _C_ATOM:
|
||||
case _C_CHARPTR:
|
||||
return sizeof(char*);
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi(type+1);
|
||||
while (isdigit(*++type));
|
||||
return len*objc_aligned_size (type);
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* padd to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
return acc_size;
|
||||
}
|
||||
|
||||
case _C_UNION_B:
|
||||
{
|
||||
int max_size = 0;
|
||||
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
|
||||
while (*type != _C_UNION_E)
|
||||
{
|
||||
max_size = MAX (max_size, objc_sizeof_type (type));
|
||||
type = objc_skip_typespec (type);
|
||||
}
|
||||
return max_size;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return the alignment of an object specified by type
|
||||
*/
|
||||
|
||||
int
|
||||
objc_alignof_type(const char* type)
|
||||
{
|
||||
switch(*type) {
|
||||
case _C_ID:
|
||||
return __alignof__(id);
|
||||
break;
|
||||
|
||||
case _C_CLASS:
|
||||
return __alignof__(Class);
|
||||
break;
|
||||
|
||||
case _C_SEL:
|
||||
return __alignof__(SEL);
|
||||
break;
|
||||
|
||||
case _C_CHR:
|
||||
return __alignof__(char);
|
||||
break;
|
||||
|
||||
case _C_UCHR:
|
||||
return __alignof__(unsigned char);
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
return __alignof__(short);
|
||||
break;
|
||||
|
||||
case _C_USHT:
|
||||
return __alignof__(unsigned short);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
return __alignof__(int);
|
||||
break;
|
||||
|
||||
case _C_UINT:
|
||||
return __alignof__(unsigned int);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
return __alignof__(long);
|
||||
break;
|
||||
|
||||
case _C_ULNG:
|
||||
return __alignof__(unsigned long);
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
return __alignof__(float);
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
return __alignof__(double);
|
||||
break;
|
||||
|
||||
case _C_PTR:
|
||||
case _C_ATOM:
|
||||
case _C_CHARPTR:
|
||||
return __alignof__(char*);
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
while (isdigit(*++type)) /* do nothing */;
|
||||
return objc_alignof_type (type);
|
||||
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
struct { int x; double y; } fooalign;
|
||||
while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
|
||||
if (*type != _C_STRUCT_E)
|
||||
return MAX (objc_alignof_type (type), __alignof__ (fooalign));
|
||||
else
|
||||
return __alignof__ (fooalign);
|
||||
}
|
||||
|
||||
case _C_UNION_B:
|
||||
{
|
||||
int maxalign = 0;
|
||||
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
|
||||
while (*type != _C_UNION_E)
|
||||
{
|
||||
maxalign = MAX (maxalign, objc_alignof_type (type));
|
||||
type = objc_skip_typespec (type);
|
||||
}
|
||||
return maxalign;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The aligned size if the size rounded up to the nearest alignment.
|
||||
*/
|
||||
|
||||
int
|
||||
objc_aligned_size (const char* type)
|
||||
{
|
||||
int size = objc_sizeof_type (type);
|
||||
int align = objc_alignof_type (type);
|
||||
return ROUND (size, align);
|
||||
}
|
||||
|
||||
/*
|
||||
The size rounded up to the nearest integral of the wordsize, taken
|
||||
to be the size of a void*.
|
||||
*/
|
||||
|
||||
int
|
||||
objc_promoted_size (const char* type)
|
||||
{
|
||||
int size = objc_sizeof_type (type);
|
||||
int wordsize = sizeof (void*);
|
||||
|
||||
return ROUND (size, wordsize);
|
||||
}
|
||||
|
||||
/*
|
||||
Skip type qualifiers. These may eventually precede typespecs
|
||||
occurring in method prototype encodings.
|
||||
*/
|
||||
|
||||
inline const char*
|
||||
objc_skip_type_qualifiers (const char* type)
|
||||
{
|
||||
while (*type == _C_CONST
|
||||
|| *type == _C_IN
|
||||
|| *type == _C_INOUT
|
||||
|| *type == _C_OUT
|
||||
|| *type == _C_BYCOPY
|
||||
|| *type == _C_ONEWAY)
|
||||
{
|
||||
type += 1;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Skip one typespec element. If the typespec is prepended by type
|
||||
qualifiers, these are skipped as well.
|
||||
*/
|
||||
|
||||
const char*
|
||||
objc_skip_typespec (const char* type)
|
||||
{
|
||||
type = objc_skip_type_qualifiers (type);
|
||||
|
||||
switch (*type) {
|
||||
|
||||
case _C_ID:
|
||||
/* An id may be annotated by the actual type if it is known
|
||||
with the @"ClassName" syntax */
|
||||
|
||||
if (*++type != '"')
|
||||
return type;
|
||||
else
|
||||
{
|
||||
while (*++type != '"') /* do nothing */;
|
||||
return type + 1;
|
||||
}
|
||||
|
||||
/* The following are one character type codes */
|
||||
case _C_CLASS:
|
||||
case _C_SEL:
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
case _C_CHARPTR:
|
||||
case _C_ATOM:
|
||||
case _C_SHT:
|
||||
case _C_USHT:
|
||||
case _C_INT:
|
||||
case _C_UINT:
|
||||
case _C_LNG:
|
||||
case _C_ULNG:
|
||||
case _C_FLT:
|
||||
case _C_DBL:
|
||||
case _C_VOID:
|
||||
case _C_UNDEF:
|
||||
return ++type;
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
/* skip digits, typespec and closing ']' */
|
||||
|
||||
while(isdigit(*++type));
|
||||
type = objc_skip_typespec(type);
|
||||
if (*type == _C_ARY_E)
|
||||
return ++type;
|
||||
else
|
||||
{
|
||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case _C_STRUCT_B:
|
||||
/* skip name, and elements until closing '}' */
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '=');
|
||||
while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
|
||||
return ++type;
|
||||
|
||||
case _C_UNION_B:
|
||||
/* skip name, and elements until closing ')' */
|
||||
|
||||
while (*type != _C_UNION_E && *type++ != '=');
|
||||
while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
|
||||
return ++type;
|
||||
|
||||
case _C_PTR:
|
||||
/* Just skip the following typespec */
|
||||
|
||||
return objc_skip_typespec (++type);
|
||||
|
||||
default:
|
||||
{
|
||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Skip an offset as part of a method encoding. This is prepended by a
|
||||
'+' if the argument is passed in registers.
|
||||
*/
|
||||
inline const char*
|
||||
objc_skip_offset (const char* type)
|
||||
{
|
||||
if (*type == '+') type++;
|
||||
while(isdigit(*++type));
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
Skip an argument specification of a method encoding.
|
||||
*/
|
||||
const char*
|
||||
objc_skip_argspec (const char* type)
|
||||
{
|
||||
type = objc_skip_typespec (type);
|
||||
type = objc_skip_offset (type);
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the number of arguments that the method MTH expects.
|
||||
Note that all methods need two implicit arguments `self' and
|
||||
`_cmd'.
|
||||
*/
|
||||
int
|
||||
method_get_number_of_arguments (struct objc_method* mth)
|
||||
{
|
||||
int i = 0;
|
||||
const char* type = mth->method_types;
|
||||
while (*type)
|
||||
{
|
||||
type = objc_skip_argspec (type);
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the size of the argument block needed on the stack to invoke
|
||||
the method MTH. This may be zero, if all arguments are passed in
|
||||
registers.
|
||||
*/
|
||||
|
||||
int
|
||||
method_get_sizeof_arguments (struct objc_method* mth)
|
||||
{
|
||||
const char* type = objc_skip_typespec (mth->method_types);
|
||||
return atoi (type);
|
||||
}
|
||||
|
||||
/*
|
||||
Return a pointer to the next argument of ARGFRAME. type points to
|
||||
the last argument. Typical use of this look like:
|
||||
|
||||
{
|
||||
char *datum, *type;
|
||||
for (datum = method_get_first_argument (method, argframe, &type);
|
||||
datum; datum = method_get_next_argument (argframe, &type))
|
||||
{
|
||||
unsigned flags = objc_get_type_qualifiers (type);
|
||||
type = objc_skip_type_qualifiers (type);
|
||||
if (*type != _C_PTR)
|
||||
[portal encodeData: datum ofType: type];
|
||||
else
|
||||
{
|
||||
if ((flags & _F_IN) == _F_IN)
|
||||
[portal encodeData: *(char**)datum ofType: ++type];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
char*
|
||||
method_get_next_argument (arglist_t argframe,
|
||||
const char **type)
|
||||
{
|
||||
const char *t = objc_skip_argspec (*type);
|
||||
|
||||
if (*t == '\0')
|
||||
return 0;
|
||||
|
||||
*type = t;
|
||||
t = objc_skip_typespec (t);
|
||||
|
||||
if (*t == '+')
|
||||
return argframe->arg_regs + atoi (++t);
|
||||
else
|
||||
return argframe->arg_ptr + atoi (t);
|
||||
}
|
||||
|
||||
/*
|
||||
Return a pointer to the value of the first argument of the method
|
||||
described in M with the given argumentframe ARGFRAME. The type
|
||||
is returned in TYPE. type must be passed to successive calls of
|
||||
method_get_next_argument.
|
||||
*/
|
||||
char*
|
||||
method_get_first_argument (struct objc_method* m,
|
||||
arglist_t argframe,
|
||||
const char** type)
|
||||
{
|
||||
*type = m->method_types;
|
||||
return method_get_next_argument (argframe, type);
|
||||
}
|
||||
|
||||
/*
|
||||
Return a pointer to the ARGth argument of the method
|
||||
M from the frame ARGFRAME. The type of the argument
|
||||
is returned in the value-result argument TYPE
|
||||
*/
|
||||
|
||||
char*
|
||||
method_get_nth_argument (struct objc_method* m,
|
||||
arglist_t argframe, int arg,
|
||||
const char **type)
|
||||
{
|
||||
const char* t = objc_skip_argspec (m->method_types);
|
||||
|
||||
if (arg > method_get_number_of_arguments (m))
|
||||
return 0;
|
||||
|
||||
while (arg--)
|
||||
t = objc_skip_argspec (t);
|
||||
|
||||
*type = t;
|
||||
t = objc_skip_typespec (t);
|
||||
|
||||
if (*t == '+')
|
||||
return argframe->arg_regs + atoi (++t);
|
||||
else
|
||||
return argframe->arg_ptr + atoi (t);
|
||||
}
|
||||
|
||||
unsigned
|
||||
objc_get_type_qualifiers (const char* type)
|
||||
{
|
||||
unsigned res = 0;
|
||||
BOOL flag = YES;
|
||||
|
||||
while (flag)
|
||||
switch (*type++)
|
||||
{
|
||||
case _C_CONST: res |= _F_CONST; break;
|
||||
case _C_IN: res |= _F_IN; break;
|
||||
case _C_INOUT: res |= _F_INOUT; break;
|
||||
case _C_OUT: res |= _F_OUT; break;
|
||||
case _C_BYCOPY: res |= _F_BYCOPY; break;
|
||||
case _C_ONEWAY: res |= _F_ONEWAY; break;
|
||||
default: flag = NO;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* Encoding of types for Objective C.
|
||||
Copyright (C) 1993, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Author: Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __encoding_INCLUDE_GNU
|
||||
#define __encoding_INCLUDE_GNU
|
||||
|
||||
#include <ctype.h>
|
||||
#include "objc/objc-api.h"
|
||||
|
||||
#define _C_CONST 'r'
|
||||
#define _C_IN 'n'
|
||||
#define _C_INOUT 'N'
|
||||
#define _C_OUT 'o'
|
||||
#define _C_BYCOPY 'O'
|
||||
#define _C_ONEWAY 'V'
|
||||
|
||||
#define _F_CONST 0x01
|
||||
#define _F_IN 0x01
|
||||
#define _F_OUT 0x02
|
||||
#define _F_INOUT 0x03
|
||||
#define _F_BYCOPY 0x04
|
||||
#define _F_ONEWAY 0x08
|
||||
|
||||
|
||||
int objc_aligned_size (const char* type);
|
||||
int objc_sizeof_type (const char* type);
|
||||
int objc_alignof_type (const char* type);
|
||||
int objc_aligned_size (const char* type);
|
||||
int objc_promoted_size (const char* type);
|
||||
const char* objc_skip_type_qualifiers (const char* type);
|
||||
const char* objc_skip_typespec (const char* type);
|
||||
const char* objc_skip_offset (const char* type);
|
||||
const char* objc_skip_argspec (const char* type);
|
||||
int method_get_number_of_arguments (struct objc_method*);
|
||||
int method_get_sizeof_arguments (struct objc_method*);
|
||||
|
||||
char* method_get_first_argument (struct objc_method*,
|
||||
arglist_t argframe,
|
||||
const char** type);
|
||||
char* method_get_next_argument (arglist_t argframe,
|
||||
const char **type);
|
||||
char* method_get_nth_argument (struct objc_method* m,
|
||||
arglist_t argframe,
|
||||
int arg,
|
||||
const char **type);
|
||||
|
||||
unsigned objc_get_type_qualifiers (const char* type);
|
||||
|
||||
|
||||
#endif /* __encoding_INCLUDE_GNU */
|
||||
|
|
@ -1,283 +0,0 @@
|
|||
/* Hash tables for Objective C internal structures
|
||||
Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include "objc/hash.h"
|
||||
|
||||
#include "runtime.h" /* for DEBUG_PRINTF */
|
||||
|
||||
/* These two macros determine when a hash table is full and
|
||||
by how much it should be expanded respectively.
|
||||
|
||||
These equations are percentages. */
|
||||
#define FULLNESS(cache) \
|
||||
((((cache)->size * 75) / 100) <= (cache)->used)
|
||||
#define EXPANSION(cache) \
|
||||
((cache)->size * 2)
|
||||
|
||||
cache_ptr
|
||||
hash_new (unsigned int size, hash_func_type hash_func,
|
||||
compare_func_type compare_func)
|
||||
{
|
||||
cache_ptr cache;
|
||||
|
||||
/* Pass me a value greater than 0 and a power of 2. */
|
||||
assert (size);
|
||||
assert (!(size & (size - 1)));
|
||||
|
||||
/* Allocate the cache structure. calloc insures
|
||||
its initialization for default values. */
|
||||
cache = (cache_ptr) objc_calloc (1, sizeof (struct cache));
|
||||
assert (cache);
|
||||
|
||||
/* Allocate the array of buckets for the cache.
|
||||
calloc initializes all of the pointers to NULL. */
|
||||
cache->node_table
|
||||
= (node_ptr *) objc_calloc (size, sizeof (node_ptr));
|
||||
assert (cache->node_table);
|
||||
|
||||
cache->size = size;
|
||||
|
||||
/* This should work for all processor architectures? */
|
||||
cache->mask = (size - 1);
|
||||
|
||||
/* Store the hashing function so that codes can be computed. */
|
||||
cache->hash_func = hash_func;
|
||||
|
||||
/* Store the function that compares hash keys to
|
||||
determine if they are equal. */
|
||||
cache->compare_func = compare_func;
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hash_delete (cache_ptr cache)
|
||||
{
|
||||
node_ptr node;
|
||||
node_ptr next_node;
|
||||
unsigned int i;
|
||||
|
||||
/* Purge all key/value pairs from the table. */
|
||||
/* Step through the nodes one by one and remove every node WITHOUT
|
||||
using hash_next. this makes hash_delete much more efficient. */
|
||||
for (i = 0;i < cache->size;i++) {
|
||||
if ((node = cache->node_table[i])) {
|
||||
/* an entry in the hash table has been found, now step through the
|
||||
nodes next in the list and free them. */
|
||||
while ((next_node = node->next)) {
|
||||
hash_remove (cache,node->key);
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
hash_remove (cache,node->key);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the array of nodes and the cache itself. */
|
||||
objc_free(cache->node_table);
|
||||
objc_free(cache);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hash_add (cache_ptr *cachep, const void *key, void *value)
|
||||
{
|
||||
size_t indx = (*(*cachep)->hash_func)(*cachep, key);
|
||||
node_ptr node = (node_ptr) objc_calloc (1, sizeof (struct cache_node));
|
||||
|
||||
|
||||
assert (node);
|
||||
|
||||
/* Initialize the new node. */
|
||||
node->key = key;
|
||||
node->value = value;
|
||||
node->next = (*cachep)->node_table[indx];
|
||||
|
||||
/* Debugging.
|
||||
Check the list for another key. */
|
||||
#ifdef DEBUG
|
||||
{ node_ptr node1 = (*cachep)->node_table[indx];
|
||||
|
||||
while (node1) {
|
||||
|
||||
assert (node1->key != key);
|
||||
node1 = node1->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Install the node as the first element on the list. */
|
||||
(*cachep)->node_table[indx] = node;
|
||||
|
||||
/* Bump the number of entries in the cache. */
|
||||
++(*cachep)->used;
|
||||
|
||||
/* Check the hash table's fullness. We're going
|
||||
to expand if it is above the fullness level. */
|
||||
if (FULLNESS (*cachep)) {
|
||||
|
||||
/* The hash table has reached its fullness level. Time to
|
||||
expand it.
|
||||
|
||||
I'm using a slow method here but is built on other
|
||||
primitive functions thereby increasing its
|
||||
correctness. */
|
||||
node_ptr node1 = NULL;
|
||||
cache_ptr new = hash_new (EXPANSION (*cachep),
|
||||
(*cachep)->hash_func,
|
||||
(*cachep)->compare_func);
|
||||
|
||||
DEBUG_PRINTF ("Expanding cache %#x from %d to %d\n",
|
||||
*cachep, (*cachep)->size, new->size);
|
||||
|
||||
/* Copy the nodes from the first hash table to the new one. */
|
||||
while ((node1 = hash_next (*cachep, node1)))
|
||||
hash_add (&new, node1->key, node1->value);
|
||||
|
||||
/* Trash the old cache. */
|
||||
hash_delete (*cachep);
|
||||
|
||||
/* Return a pointer to the new hash table. */
|
||||
*cachep = new;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hash_remove (cache_ptr cache, const void *key)
|
||||
{
|
||||
size_t indx = (*cache->hash_func)(cache, key);
|
||||
node_ptr node = cache->node_table[indx];
|
||||
|
||||
|
||||
/* We assume there is an entry in the table. Error if it is not. */
|
||||
assert (node);
|
||||
|
||||
/* Special case. First element is the key/value pair to be removed. */
|
||||
if ((*cache->compare_func)(node->key, key)) {
|
||||
cache->node_table[indx] = node->next;
|
||||
objc_free(node);
|
||||
} else {
|
||||
|
||||
/* Otherwise, find the hash entry. */
|
||||
node_ptr prev = node;
|
||||
BOOL removed = NO;
|
||||
|
||||
do {
|
||||
|
||||
if ((*cache->compare_func)(node->key, key)) {
|
||||
prev->next = node->next, removed = YES;
|
||||
objc_free(node);
|
||||
} else
|
||||
prev = node, node = node->next;
|
||||
} while (!removed && node);
|
||||
assert (removed);
|
||||
}
|
||||
|
||||
/* Decrement the number of entries in the hash table. */
|
||||
--cache->used;
|
||||
}
|
||||
|
||||
|
||||
node_ptr
|
||||
hash_next (cache_ptr cache, node_ptr node)
|
||||
{
|
||||
/* If the scan is being started then reset the last node
|
||||
visitied pointer and bucket index. */
|
||||
if (!node)
|
||||
cache->last_bucket = 0;
|
||||
|
||||
/* If there is a node visited last then check for another
|
||||
entry in the same bucket; Otherwise step to the next bucket. */
|
||||
if (node) {
|
||||
if (node->next)
|
||||
/* There is a node which follows the last node
|
||||
returned. Step to that node and retun it. */
|
||||
return node->next;
|
||||
else
|
||||
++cache->last_bucket;
|
||||
}
|
||||
|
||||
/* If the list isn't exhausted then search the buckets for
|
||||
other nodes. */
|
||||
if (cache->last_bucket < cache->size) {
|
||||
/* Scan the remainder of the buckets looking for an entry
|
||||
at the head of the list. Return the first item found. */
|
||||
while (cache->last_bucket < cache->size)
|
||||
if (cache->node_table[cache->last_bucket])
|
||||
return cache->node_table[cache->last_bucket];
|
||||
else
|
||||
++cache->last_bucket;
|
||||
|
||||
/* No further nodes were found in the hash table. */
|
||||
return NULL;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Given KEY, return corresponding value for it in CACHE.
|
||||
Return NULL if the KEY is not recorded. */
|
||||
|
||||
void *
|
||||
hash_value_for_key (cache_ptr cache, const void *key)
|
||||
{
|
||||
node_ptr node = cache->node_table[(*cache->hash_func)(cache, key)];
|
||||
void *retval = NULL;
|
||||
|
||||
if (node)
|
||||
do {
|
||||
if ((*cache->compare_func)(node->key, key)) {
|
||||
retval = node->value;
|
||||
break;
|
||||
} else
|
||||
node = node->next;
|
||||
} while (!retval && node);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Given KEY, return YES if it exists in the CACHE.
|
||||
Return NO if it does not */
|
||||
|
||||
BOOL
|
||||
hash_is_key_in_hash (cache_ptr cache, const void *key)
|
||||
{
|
||||
node_ptr node = cache->node_table[(*cache->hash_func)(cache, key)];
|
||||
|
||||
if (node)
|
||||
do {
|
||||
if ((*cache->compare_func)(node->key, key))
|
||||
return YES;
|
||||
else
|
||||
node = node->next;
|
||||
} while (node);
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
/* Hash tables for Objective C method dispatch.
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
|
||||
#ifndef __hash_INCLUDE_GNU
|
||||
#define __hash_INCLUDE_GNU
|
||||
|
||||
#include <stddef.h>
|
||||
#include <objc/objc.h>
|
||||
|
||||
/*
|
||||
* This data structure is used to hold items
|
||||
* stored in a hash table. Each node holds
|
||||
* a key/value pair.
|
||||
*
|
||||
* Items in the cache are really of type void *.
|
||||
*/
|
||||
typedef struct cache_node
|
||||
{
|
||||
struct cache_node *next; /* Pointer to next entry on the list.
|
||||
NULL indicates end of list. */
|
||||
const void *key; /* Key used to locate the value. Used
|
||||
to locate value when more than one
|
||||
key computes the same hash
|
||||
value. */
|
||||
void *value; /* Value stored for the key. */
|
||||
} *node_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* This data type is the function that computes a hash code given a key.
|
||||
* Therefore, the key can be a pointer to anything and the function specific
|
||||
* to the key type.
|
||||
*
|
||||
* Unfortunately there is a mutual data structure reference problem with this
|
||||
* typedef. Therefore, to remove compiler warnings the functions passed to
|
||||
* hash_new will have to be casted to this type.
|
||||
*/
|
||||
typedef unsigned int (*hash_func_type)(void *, const void *);
|
||||
|
||||
/*
|
||||
* This data type is the function that compares two hash keys and returns an
|
||||
* integer greater than, equal to, or less than 0, according as the first
|
||||
* parameter is lexicographically greater than, equal to, or less than the
|
||||
* second.
|
||||
*/
|
||||
|
||||
typedef int (*compare_func_type)(const void *, const void *);
|
||||
|
||||
|
||||
/*
|
||||
* This data structure is the cache.
|
||||
*
|
||||
* It must be passed to all of the hashing routines
|
||||
* (except for new).
|
||||
*/
|
||||
typedef struct cache
|
||||
{
|
||||
/* Variables used to implement the hash itself. */
|
||||
node_ptr *node_table; /* Pointer to an array of hash nodes. */
|
||||
/* Variables used to track the size of the hash table so to determine
|
||||
when to resize it. */
|
||||
unsigned int size; /* Number of buckets allocated for the hash table
|
||||
(number of array entries allocated for
|
||||
"node_table"). Must be a power of two. */
|
||||
unsigned int used; /* Current number of entries in the hash table. */
|
||||
unsigned int mask; /* Precomputed mask. */
|
||||
|
||||
/* Variables used to implement indexing through the hash table. */
|
||||
|
||||
unsigned int last_bucket; /* Tracks which entry in the array where
|
||||
the last value was returned. */
|
||||
/* Function used to compute a hash code given a key.
|
||||
This function is specified when the hash table is created. */
|
||||
hash_func_type hash_func;
|
||||
/* Function used to compare two hash keys to see if they are equal. */
|
||||
compare_func_type compare_func;
|
||||
} *cache_ptr;
|
||||
|
||||
|
||||
/* Two important hash tables. */
|
||||
extern cache_ptr module_hash_table, class_hash_table;
|
||||
|
||||
/* Allocate and initialize a hash table. */
|
||||
|
||||
cache_ptr hash_new (unsigned int size,
|
||||
hash_func_type hash_func,
|
||||
compare_func_type compare_func);
|
||||
|
||||
/* Deallocate all of the hash nodes and the cache itself. */
|
||||
|
||||
void hash_delete (cache_ptr cache);
|
||||
|
||||
/* Add the key/value pair to the hash table. If the
|
||||
hash table reaches a level of fullness then it will be resized.
|
||||
|
||||
assert if the key is already in the hash. */
|
||||
|
||||
void hash_add (cache_ptr *cachep, const void *key, void *value);
|
||||
|
||||
/* Remove the key/value pair from the hash table.
|
||||
assert if the key isn't in the table. */
|
||||
|
||||
void hash_remove (cache_ptr cache, const void *key);
|
||||
|
||||
/* Used to index through the hash table. Start with NULL
|
||||
to get the first entry.
|
||||
|
||||
Successive calls pass the value returned previously.
|
||||
** Don't modify the hash during this operation ***
|
||||
|
||||
Cache nodes are returned such that key or value can
|
||||
be extracted. */
|
||||
|
||||
node_ptr hash_next (cache_ptr cache, node_ptr node);
|
||||
|
||||
/* Used to return a value from a hash table using a given key. */
|
||||
|
||||
void *hash_value_for_key (cache_ptr cache, const void *key);
|
||||
|
||||
/* Used to determine if the given key exists in the hash table */
|
||||
|
||||
BOOL hash_is_key_in_hash (cache_ptr cache, const void *key);
|
||||
|
||||
/************************************************
|
||||
|
||||
Useful hashing functions.
|
||||
|
||||
Declared inline for your pleasure.
|
||||
|
||||
************************************************/
|
||||
|
||||
/* Calculate a hash code by performing some
|
||||
manipulation of the key pointer. (Use the lowest bits
|
||||
except for those likely to be 0 due to alignment.) */
|
||||
|
||||
static inline unsigned int
|
||||
hash_ptr (cache_ptr cache, const void *key)
|
||||
{
|
||||
return ((size_t)key / sizeof (void *)) & cache->mask;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate a hash code by iterating over a NULL
|
||||
terminate string. */
|
||||
static inline unsigned int
|
||||
hash_string (cache_ptr cache, const void *key)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
unsigned int ctr = 0;
|
||||
|
||||
|
||||
while (*(char*)key) {
|
||||
ret ^= *(char*)key++ << ctr;
|
||||
ctr = (ctr + 1) % sizeof (void *);
|
||||
}
|
||||
|
||||
return ret & cache->mask;
|
||||
}
|
||||
|
||||
|
||||
/* Compare two pointers for equality. */
|
||||
static inline int
|
||||
compare_ptrs (const void *k1, const void *k2)
|
||||
{
|
||||
return !(k1 - k2);
|
||||
}
|
||||
|
||||
|
||||
/* Compare two strings. */
|
||||
static inline int
|
||||
compare_strings (const void *k1, const void *k2)
|
||||
{
|
||||
if (k1 == k2)
|
||||
return 1;
|
||||
else if (k1 == 0 || k2 == 0)
|
||||
return 0;
|
||||
else
|
||||
return !strcmp (k1, k2);
|
||||
}
|
||||
|
||||
|
||||
#endif /* not __hash_INCLUDE_GNU */
|
||||
|
|
@ -1,834 +0,0 @@
|
|||
/* GNU Objective C Runtime initialization
|
||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
+load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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
|
||||
GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#include "runtime.h"
|
||||
|
||||
/* The version number of this runtime. This must match the number
|
||||
defined in gcc (objc-act.c) */
|
||||
#define OBJC_VERSION 8
|
||||
#define PROTOCOL_VERSION 2
|
||||
|
||||
/* This list contains all modules currently loaded into the runtime */
|
||||
static struct objc_list* __objc_module_list = 0; /* !T:MUTEX */
|
||||
|
||||
/* This list contains all proto_list's not yet assigned class links */
|
||||
static struct objc_list* unclaimed_proto_list = 0; /* !T:MUTEX */
|
||||
|
||||
/* List of unresolved static instances. */
|
||||
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
|
||||
|
||||
/* Global runtime "write" mutex. */
|
||||
objc_mutex_t __objc_runtime_mutex = 0;
|
||||
|
||||
/* Number of threads that are alive. */
|
||||
int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
|
||||
|
||||
/* Check compiler vs runtime version */
|
||||
static void init_check_module_version (Module_t);
|
||||
|
||||
/* Assign isa links to protos */
|
||||
static void __objc_init_protocols (struct objc_protocol_list* protos);
|
||||
|
||||
/* Add protocol to class */
|
||||
static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
|
||||
|
||||
/* This is a hook which is called by __objc_exec_class every time a class
|
||||
or a category is loaded into the runtime. This may e.g. help a
|
||||
dynamic loader determine the classes that have been loaded when
|
||||
an object file is dynamically linked in */
|
||||
void (*_objc_load_callback)(Class class, Category* category); /* !T:SAFE */
|
||||
|
||||
/* Is all categories/classes resolved? */
|
||||
BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
|
||||
|
||||
extern SEL
|
||||
__sel_register_typed_name (const char *name, const char *types,
|
||||
struct objc_selector *orig, BOOL is_const);
|
||||
|
||||
/* Sends +load to all classes and categories in certain situations. */
|
||||
static void objc_send_load (void);
|
||||
|
||||
/* Inserts all the classes defined in module in a tree of classes that
|
||||
resembles the class hierarchy. This tree is traversed in preorder and the
|
||||
classes in its nodes receive the +load message if these methods were not
|
||||
executed before. The algorithm ensures that when the +load method of a class
|
||||
is executed all the superclasses have been already received the +load
|
||||
message. */
|
||||
static void __objc_create_classes_tree (Module_t module);
|
||||
|
||||
static void __objc_call_callback (Module_t module);
|
||||
|
||||
/* A special version that works only before the classes are completely
|
||||
installed in the runtime. */
|
||||
static BOOL class_is_subclass_of_class (Class class, Class superclass);
|
||||
|
||||
typedef struct objc_class_tree {
|
||||
Class class;
|
||||
struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
|
||||
} objc_class_tree;
|
||||
|
||||
/* This is a linked list of objc_class_tree trees. The head of these trees
|
||||
are root classes (their super class is Nil). These different trees
|
||||
represent different class hierarchies. */
|
||||
static struct objc_list *__objc_class_tree_list = NULL;
|
||||
|
||||
/* Keeps the +load methods who have been already executed. This hash should
|
||||
not be destroyed during the execution of the program. */
|
||||
static cache_ptr __objc_load_methods = NULL;
|
||||
|
||||
/* Creates a tree of classes whose topmost class is directly inherited from
|
||||
`upper' and the bottom class in this tree is `bottom_class'. The classes
|
||||
in this tree are super classes of `bottom_class'. `subclasses' member
|
||||
of each tree node point to the next subclass tree node. */
|
||||
static objc_class_tree *
|
||||
create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||
{
|
||||
Class superclass = bottom_class->super_class ?
|
||||
objc_lookup_class ((char*)bottom_class->super_class)
|
||||
: Nil;
|
||||
|
||||
objc_class_tree *tree, *prev;
|
||||
|
||||
DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
|
||||
DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
|
||||
(bottom_class ? bottom_class->name : NULL),
|
||||
(upper ? upper->name : NULL));
|
||||
|
||||
tree = prev = objc_calloc (1, sizeof (objc_class_tree));
|
||||
prev->class = bottom_class;
|
||||
|
||||
while (superclass != upper)
|
||||
{
|
||||
tree = objc_calloc (1, sizeof (objc_class_tree));
|
||||
tree->class = superclass;
|
||||
tree->subclasses = list_cons (prev, tree->subclasses);
|
||||
superclass = (superclass->super_class ?
|
||||
objc_lookup_class ((char*)superclass->super_class)
|
||||
: Nil);
|
||||
prev = tree;
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Insert the `class' into the proper place in the `tree' class hierarchy. This
|
||||
function returns a new tree if the class has been successfully inserted into
|
||||
the tree or NULL if the class is not part of the classes hierarchy described
|
||||
by `tree'. This function is private to objc_tree_insert_class(), you should
|
||||
not call it directly. */
|
||||
static objc_class_tree *
|
||||
__objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||
{
|
||||
DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
|
||||
tree, class->name);
|
||||
|
||||
if (tree == NULL)
|
||||
return create_tree_of_subclasses_inherited_from (class, NULL);
|
||||
else if (class == tree->class)
|
||||
{
|
||||
/* `class' has been already inserted */
|
||||
DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
|
||||
return tree;
|
||||
}
|
||||
else if ((class->super_class ?
|
||||
objc_lookup_class ((char*)class->super_class)
|
||||
: Nil)
|
||||
== tree->class)
|
||||
{
|
||||
/* If class is a direct subclass of tree->class then add class to the
|
||||
list of subclasses. First check to see if it wasn't already
|
||||
inserted. */
|
||||
struct objc_list *list = tree->subclasses;
|
||||
objc_class_tree *node;
|
||||
|
||||
while (list)
|
||||
{
|
||||
/* Class has been already inserted; do nothing just return
|
||||
the tree. */
|
||||
if (((objc_class_tree*)list->head)->class == class)
|
||||
{
|
||||
DEBUG_PRINTF ("2. class %s was previously inserted\n",
|
||||
class->name);
|
||||
return tree;
|
||||
}
|
||||
list = list->tail;
|
||||
}
|
||||
|
||||
/* Create a new node class and insert it into the list of subclasses */
|
||||
node = objc_calloc (1, sizeof (objc_class_tree));
|
||||
node->class = class;
|
||||
tree->subclasses = list_cons (node, tree->subclasses);
|
||||
DEBUG_PRINTF ("3. class %s inserted\n", class->name);
|
||||
return tree;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The class is not a direct subclass of tree->class. Search for class's
|
||||
superclasses in the list of subclasses. */
|
||||
struct objc_list *subclasses = tree->subclasses;
|
||||
|
||||
/* Precondition: the class must be a subclass of tree->class; otherwise
|
||||
return NULL to indicate our caller that it must take the next tree. */
|
||||
if (!class_is_subclass_of_class (class, tree->class))
|
||||
return NULL;
|
||||
|
||||
for (; subclasses != NULL; subclasses = subclasses->tail)
|
||||
{
|
||||
Class aClass = ((objc_class_tree*)(subclasses->head))->class;
|
||||
|
||||
if (class_is_subclass_of_class (class, aClass))
|
||||
{
|
||||
/* If we found one of class's superclasses we insert the class
|
||||
into its subtree and return the original tree since nothing
|
||||
has been changed. */
|
||||
subclasses->head
|
||||
= __objc_tree_insert_class (subclasses->head, class);
|
||||
DEBUG_PRINTF ("4. class %s inserted\n", class->name);
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
||||
/* We haven't found a subclass of `class' in the `subclasses' list.
|
||||
Create a new tree of classes whose topmost class is a direct subclass
|
||||
of tree->class. */
|
||||
{
|
||||
objc_class_tree *new_tree
|
||||
= create_tree_of_subclasses_inherited_from (class, tree->class);
|
||||
tree->subclasses = list_cons (new_tree, tree->subclasses);
|
||||
DEBUG_PRINTF ("5. class %s inserted\n", class->name);
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function inserts `class' in the right tree hierarchy classes. */
|
||||
static void
|
||||
objc_tree_insert_class (Class class)
|
||||
{
|
||||
struct objc_list *list_node;
|
||||
objc_class_tree *tree;
|
||||
|
||||
list_node = __objc_class_tree_list;
|
||||
while (list_node)
|
||||
{
|
||||
tree = __objc_tree_insert_class (list_node->head, class);
|
||||
if (tree)
|
||||
{
|
||||
list_node->head = tree;
|
||||
break;
|
||||
}
|
||||
else
|
||||
list_node = list_node->tail;
|
||||
}
|
||||
|
||||
/* If the list was finished but the class hasn't been inserted, insert it
|
||||
here. */
|
||||
if (!list_node)
|
||||
{
|
||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
||||
__objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
|
||||
}
|
||||
}
|
||||
|
||||
/* Traverse tree in preorder. Used to send +load. */
|
||||
static void
|
||||
objc_preorder_traverse (objc_class_tree *tree,
|
||||
int level,
|
||||
void (*function)(objc_class_tree*, int))
|
||||
{
|
||||
struct objc_list *node;
|
||||
|
||||
(*function) (tree, level);
|
||||
for (node = tree->subclasses; node; node = node->tail)
|
||||
objc_preorder_traverse (node->head, level + 1, function);
|
||||
}
|
||||
|
||||
/* Traverse tree in postorder. Used to destroy a tree. */
|
||||
static void
|
||||
objc_postorder_traverse (objc_class_tree *tree,
|
||||
int level,
|
||||
void (*function)(objc_class_tree*, int))
|
||||
{
|
||||
struct objc_list *node;
|
||||
|
||||
for (node = tree->subclasses; node; node = node->tail)
|
||||
objc_postorder_traverse (node->head, level + 1, function);
|
||||
(*function) (tree, level);
|
||||
}
|
||||
|
||||
/* Used to print a tree class hierarchy. */
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
__objc_tree_print (objc_class_tree *tree, int level)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < level; i++)
|
||||
printf (" ");
|
||||
printf ("%s\n", tree->class->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Walks on a linked list of methods in the reverse order and executes all
|
||||
the methods corresponding to `op' selector. Walking in the reverse order
|
||||
assures the +load of class is executed first and then +load of categories
|
||||
because of the way in which categories are added to the class methods. */
|
||||
static void
|
||||
__objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!method_list)
|
||||
return;
|
||||
|
||||
/* First execute the `op' message in the following method lists */
|
||||
__objc_send_message_in_list (method_list->method_next, class, op);
|
||||
|
||||
/* Search the method list. */
|
||||
for (i = 0; i < method_list->method_count; i++)
|
||||
{
|
||||
Method_t mth = &method_list->method_list[i];
|
||||
|
||||
if (mth->method_name && sel_eq (mth->method_name, op)
|
||||
&& !hash_is_key_in_hash (__objc_load_methods, mth->method_name))
|
||||
{
|
||||
/* The method was found and wasn't previously executed. */
|
||||
(*mth->method_imp) ((id)class, mth->method_name);
|
||||
|
||||
/* Add this method into the +load hash table */
|
||||
hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
|
||||
|
||||
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_send_load (objc_class_tree *tree, int level)
|
||||
{
|
||||
static SEL load_sel = 0;
|
||||
Class class = tree->class;
|
||||
MethodList_t method_list = class->class_pointer->methods;
|
||||
|
||||
if (!load_sel)
|
||||
load_sel = sel_register_name ("load");
|
||||
|
||||
__objc_send_message_in_list (method_list, class, load_sel);
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_destroy_class_tree_node (objc_class_tree *tree, int level)
|
||||
{
|
||||
objc_free (tree);
|
||||
}
|
||||
|
||||
/* This is used to check if the relationship between two classes before the
|
||||
runtime completely installs the classes. */
|
||||
static BOOL
|
||||
class_is_subclass_of_class (Class class, Class superclass)
|
||||
{
|
||||
for (; class != Nil;)
|
||||
{
|
||||
if (class == superclass)
|
||||
return YES;
|
||||
class = (class->super_class ?
|
||||
objc_lookup_class ((char*)class->super_class)
|
||||
: Nil);
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* This list contains all the classes in the runtime system for whom their
|
||||
superclasses are not yet know to the runtime. */
|
||||
static struct objc_list* unresolved_classes = 0;
|
||||
|
||||
/* Static function used to reference the Object and NXConstantString classes.
|
||||
*/
|
||||
static void
|
||||
__objc_force_linking (void)
|
||||
{
|
||||
extern void __objc_linking (void);
|
||||
__objc_linking ();
|
||||
|
||||
/* Call the function to avoid compiler warning */
|
||||
__objc_force_linking ();
|
||||
}
|
||||
|
||||
/* Run through the statics list, removing modules as soon as all its statics
|
||||
have been initialized. */
|
||||
static void
|
||||
objc_init_statics (void)
|
||||
{
|
||||
struct objc_list **cell = &uninitialized_statics;
|
||||
struct objc_static_instances **statics_in_module;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
while (*cell)
|
||||
{
|
||||
int module_initialized = 1;
|
||||
|
||||
for (statics_in_module = (*cell)->head;
|
||||
*statics_in_module; statics_in_module++)
|
||||
{
|
||||
struct objc_static_instances *statics = *statics_in_module;
|
||||
Class class = objc_lookup_class (statics->class_name);
|
||||
|
||||
if (!class)
|
||||
module_initialized = 0;
|
||||
/* Actually, the static's class_pointer will be NULL when we
|
||||
haven't been here before. However, the comparison is to be
|
||||
reminded of taking into account class posing and to think about
|
||||
possible semantics... */
|
||||
else if (class != statics->instances[0]->class_pointer)
|
||||
{
|
||||
id *inst;
|
||||
|
||||
for (inst = &statics->instances[0]; *inst; inst++)
|
||||
{
|
||||
(*inst)->class_pointer = class;
|
||||
|
||||
/* ??? Make sure the object will not be freed. With
|
||||
refcounting, invoke `-retain'. Without refcounting, do
|
||||
nothing and hope that `-free' will never be invoked. */
|
||||
|
||||
/* ??? Send the object an `-initStatic' or something to
|
||||
that effect now or later on? What are the semantics of
|
||||
statically allocated instances, besides the trivial
|
||||
NXConstantString, anyway? */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (module_initialized)
|
||||
{
|
||||
/* Remove this module from the uninitialized list. */
|
||||
struct objc_list *this = *cell;
|
||||
*cell = this->tail;
|
||||
objc_free(this);
|
||||
}
|
||||
else
|
||||
cell = &(*cell)->tail;
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
} /* objc_init_statics */
|
||||
|
||||
/* This function is called by constructor functions generated for each
|
||||
module compiled. (_GLOBAL_$I$...) The purpose of this function is to
|
||||
gather the module pointers so that they may be processed by the
|
||||
initialization routines as soon as possible */
|
||||
|
||||
void
|
||||
__objc_exec_class (Module_t module)
|
||||
{
|
||||
/* Have we processed any constructors previously? This flag is used to
|
||||
indicate that some global data structures need to be built. */
|
||||
static BOOL previous_constructors = 0;
|
||||
|
||||
static struct objc_list* unclaimed_categories = 0;
|
||||
|
||||
/* The symbol table (defined in objc-api.h) generated by gcc */
|
||||
Symtab_t symtab = module->symtab;
|
||||
|
||||
/* The statics in this module */
|
||||
struct objc_static_instances **statics
|
||||
= symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
|
||||
|
||||
/* Entry used to traverse hash lists */
|
||||
struct objc_list** cell;
|
||||
|
||||
/* The table of selector references for this module */
|
||||
SEL selectors = symtab->refs;
|
||||
|
||||
/* dummy counter */
|
||||
int i;
|
||||
|
||||
DEBUG_PRINTF ("received module: %s\n", module->name);
|
||||
|
||||
/* check gcc version */
|
||||
init_check_module_version(module);
|
||||
|
||||
/* On the first call of this routine, initialize some data structures. */
|
||||
if (!previous_constructors)
|
||||
{
|
||||
/* Initialize thread-safe system */
|
||||
__objc_init_thread_system();
|
||||
__objc_runtime_threads_alive = 1;
|
||||
__objc_runtime_mutex = objc_mutex_allocate();
|
||||
|
||||
__objc_init_selector_tables();
|
||||
__objc_init_class_tables();
|
||||
__objc_init_dispatch_tables();
|
||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
||||
__objc_load_methods
|
||||
= hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
|
||||
previous_constructors = 1;
|
||||
}
|
||||
|
||||
/* Save the module pointer for later processing. (not currently used) */
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
__objc_module_list = list_cons(module, __objc_module_list);
|
||||
|
||||
/* Replace referenced selectors from names to SEL's. */
|
||||
if (selectors)
|
||||
{
|
||||
for (i = 0; selectors[i].sel_id; ++i)
|
||||
{
|
||||
const char *name, *type;
|
||||
name = (char*)selectors[i].sel_id;
|
||||
type = (char*)selectors[i].sel_types;
|
||||
/* Constructors are constant static data so we can safely store
|
||||
pointers to them in the runtime structures. is_const == YES */
|
||||
__sel_register_typed_name (name, type,
|
||||
(struct objc_selector*)&(selectors[i]),
|
||||
YES);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the classes in the load module and gather selector information. */
|
||||
DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
|
||||
for (i = 0; i < symtab->cls_def_cnt; ++i)
|
||||
{
|
||||
Class class = (Class) symtab->defs[i];
|
||||
const char* superclass = (char*)class->super_class;
|
||||
|
||||
/* Make sure we have what we think. */
|
||||
assert (CLS_ISCLASS(class));
|
||||
assert (CLS_ISMETA(class->class_pointer));
|
||||
DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
|
||||
|
||||
/* Initialize the subclass list to be NULL.
|
||||
In some cases it isn't and this crashes the program. */
|
||||
class->subclass_list = NULL;
|
||||
|
||||
/* Store the class in the class table and assign class numbers. */
|
||||
__objc_add_class_to_hash (class);
|
||||
|
||||
/* Register all of the selectors in the class and meta class. */
|
||||
__objc_register_selectors_from_class (class);
|
||||
__objc_register_selectors_from_class ((Class) class->class_pointer);
|
||||
|
||||
/* Install the fake dispatch tables */
|
||||
__objc_install_premature_dtable(class);
|
||||
__objc_install_premature_dtable(class->class_pointer);
|
||||
|
||||
/* Register the instance methods as class methods, this is
|
||||
only done for root classes. */
|
||||
__objc_register_instance_methods_to_class(class);
|
||||
|
||||
if (class->protocols)
|
||||
__objc_init_protocols (class->protocols);
|
||||
|
||||
/* Check to see if the superclass is known in this point. If it's not
|
||||
add the class to the unresolved_classes list. */
|
||||
if (superclass && !objc_lookup_class (superclass))
|
||||
unresolved_classes = list_cons (class, unresolved_classes);
|
||||
}
|
||||
|
||||
/* Process category information from the module. */
|
||||
for (i = 0; i < symtab->cat_def_cnt; ++i)
|
||||
{
|
||||
Category_t category = symtab->defs[i + symtab->cls_def_cnt];
|
||||
Class class = objc_lookup_class (category->class_name);
|
||||
|
||||
/* If the class for the category exists then append its methods. */
|
||||
if (class)
|
||||
{
|
||||
|
||||
DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
|
||||
module->name,
|
||||
class->name);
|
||||
|
||||
/* Do instance methods. */
|
||||
if (category->instance_methods)
|
||||
class_add_method_list (class, category->instance_methods);
|
||||
|
||||
/* Do class methods. */
|
||||
if (category->class_methods)
|
||||
class_add_method_list ((Class) class->class_pointer,
|
||||
category->class_methods);
|
||||
|
||||
if (category->protocols)
|
||||
{
|
||||
__objc_init_protocols (category->protocols);
|
||||
__objc_class_add_protocols (class, category->protocols);
|
||||
}
|
||||
|
||||
/* Register the instance methods as class methods, this is
|
||||
only done for root classes. */
|
||||
__objc_register_instance_methods_to_class(class);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The object to which the category methods belong can't be found.
|
||||
Save the information. */
|
||||
unclaimed_categories = list_cons(category, unclaimed_categories);
|
||||
}
|
||||
}
|
||||
|
||||
if (statics)
|
||||
uninitialized_statics = list_cons (statics, uninitialized_statics);
|
||||
if (uninitialized_statics)
|
||||
objc_init_statics ();
|
||||
|
||||
/* Scan the unclaimed category hash. Attempt to attach any unclaimed
|
||||
categories to objects. */
|
||||
for (cell = &unclaimed_categories;
|
||||
*cell;
|
||||
({ if (*cell) cell = &(*cell)->tail; }))
|
||||
{
|
||||
Category_t category = (*cell)->head;
|
||||
Class class = objc_lookup_class (category->class_name);
|
||||
|
||||
if (class)
|
||||
{
|
||||
DEBUG_PRINTF ("attaching stored categories to object: %s\n",
|
||||
class->name);
|
||||
|
||||
list_remove_head (cell);
|
||||
|
||||
if (category->instance_methods)
|
||||
class_add_method_list (class, category->instance_methods);
|
||||
|
||||
if (category->class_methods)
|
||||
class_add_method_list ((Class) class->class_pointer,
|
||||
category->class_methods);
|
||||
|
||||
if (category->protocols)
|
||||
{
|
||||
__objc_init_protocols (category->protocols);
|
||||
__objc_class_add_protocols (class, category->protocols);
|
||||
}
|
||||
|
||||
/* Register the instance methods as class methods, this is
|
||||
only done for root classes. */
|
||||
__objc_register_instance_methods_to_class(class);
|
||||
}
|
||||
}
|
||||
|
||||
if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
|
||||
{
|
||||
list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
|
||||
list_free (unclaimed_proto_list);
|
||||
unclaimed_proto_list = 0;
|
||||
}
|
||||
|
||||
objc_send_load ();
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
static void objc_send_load (void)
|
||||
{
|
||||
if (!__objc_module_list)
|
||||
return;
|
||||
|
||||
/* Try to find out if all the classes loaded so far also have their
|
||||
superclasses known to the runtime. We suppose that the objects that are
|
||||
allocated in the +load method are in general of a class declared in the
|
||||
same module. */
|
||||
if (unresolved_classes)
|
||||
{
|
||||
Class class = unresolved_classes->head;
|
||||
|
||||
while (objc_lookup_class ((char*)class->super_class))
|
||||
{
|
||||
list_remove_head (&unresolved_classes);
|
||||
if (unresolved_classes)
|
||||
class = unresolved_classes->head;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still have classes for whom we don't have yet their super
|
||||
* classes known to the runtime we don't send the +load messages.
|
||||
*/
|
||||
if (unresolved_classes)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Special check to allow creating and sending messages to constant strings
|
||||
in +load methods. If these classes are not yet known, even if all the
|
||||
other classes are known, delay sending of +load. */
|
||||
if (!objc_lookup_class ("NXConstantString") ||
|
||||
!objc_lookup_class ("Object"))
|
||||
return;
|
||||
|
||||
/* Iterate over all modules in the __objc_module_list and call on them the
|
||||
__objc_create_classes_tree function. This function creates a tree of
|
||||
classes that resembles the class hierarchy. */
|
||||
list_mapcar (__objc_module_list, (void(*)(void*))__objc_create_classes_tree);
|
||||
|
||||
while (__objc_class_tree_list)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
objc_preorder_traverse (__objc_class_tree_list->head,
|
||||
0, __objc_tree_print);
|
||||
#endif
|
||||
objc_preorder_traverse (__objc_class_tree_list->head,
|
||||
0, __objc_send_load);
|
||||
objc_postorder_traverse (__objc_class_tree_list->head,
|
||||
0, __objc_destroy_class_tree_node);
|
||||
list_remove_head (&__objc_class_tree_list);
|
||||
}
|
||||
|
||||
list_mapcar (__objc_module_list, (void(*)(void*))__objc_call_callback);
|
||||
list_free (__objc_module_list);
|
||||
__objc_module_list = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_create_classes_tree (Module_t module)
|
||||
{
|
||||
/* The runtime mutex is locked in this point */
|
||||
|
||||
Symtab_t symtab = module->symtab;
|
||||
int i;
|
||||
|
||||
/* Iterate thru classes defined in this module and insert them in the classes
|
||||
tree hierarchy. */
|
||||
for (i = 0; i < symtab->cls_def_cnt; i++)
|
||||
{
|
||||
Class class = (Class) symtab->defs[i];
|
||||
|
||||
objc_tree_insert_class (class);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_call_callback (Module_t module)
|
||||
{
|
||||
/* The runtime mutex is locked in this point */
|
||||
|
||||
Symtab_t symtab = module->symtab;
|
||||
int i;
|
||||
|
||||
/* Iterate thru classes defined in this module and call the callback for
|
||||
each one. */
|
||||
for (i = 0; i < symtab->cls_def_cnt; i++)
|
||||
{
|
||||
Class class = (Class) symtab->defs[i];
|
||||
|
||||
/* Call the _objc_load_callback for this class. */
|
||||
if (_objc_load_callback)
|
||||
_objc_load_callback(class, 0);
|
||||
}
|
||||
|
||||
/* Call the _objc_load_callback for categories. Don't register the instance
|
||||
methods as class methods for categories to root classes since they were
|
||||
already added in the class. */
|
||||
for (i = 0; i < symtab->cat_def_cnt; i++)
|
||||
{
|
||||
Category_t category = symtab->defs[i + symtab->cls_def_cnt];
|
||||
Class class = objc_lookup_class (category->class_name);
|
||||
|
||||
if (_objc_load_callback)
|
||||
_objc_load_callback(class, category);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check the version of gcc used to compile `module'*/
|
||||
static void init_check_module_version(Module_t module)
|
||||
{
|
||||
if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
|
||||
{
|
||||
int code;
|
||||
|
||||
if(module->version > OBJC_VERSION)
|
||||
code = OBJC_ERR_OBJC_VERSION;
|
||||
else if (module->version < OBJC_VERSION)
|
||||
code = OBJC_ERR_GCC_VERSION;
|
||||
else
|
||||
code = OBJC_ERR_MODULE_SIZE;
|
||||
|
||||
objc_error(nil, code, "Module %s version %d doesn't match runtime %d\n",
|
||||
module->name, (int)module->version, OBJC_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_init_protocols (struct objc_protocol_list* protos)
|
||||
{
|
||||
int i;
|
||||
static Class proto_class = 0;
|
||||
|
||||
if (! protos)
|
||||
return;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
if (!proto_class)
|
||||
proto_class = objc_lookup_class("Protocol");
|
||||
|
||||
if (!proto_class)
|
||||
{
|
||||
unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
assert (protos->next == 0); /* only single ones allowed */
|
||||
#endif
|
||||
|
||||
for(i = 0; i < protos->count; i++)
|
||||
{
|
||||
struct objc_protocol* aProto = protos->list[i];
|
||||
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
||||
{
|
||||
/* assign class pointer */
|
||||
aProto->class_pointer = proto_class;
|
||||
|
||||
/* init super protocols */
|
||||
__objc_init_protocols (aProto->protocol_list);
|
||||
}
|
||||
else if (protos->list[i]->class_pointer != proto_class)
|
||||
{
|
||||
objc_error(nil, OBJC_ERR_PROTOCOL_VERSION,
|
||||
"Version %d doesn't match runtime protocol version %d\n",
|
||||
(int)((char*)protos->list[i]->class_pointer-(char*)0),
|
||||
PROTOCOL_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
static void __objc_class_add_protocols (Class class,
|
||||
struct objc_protocol_list* protos)
|
||||
{
|
||||
/* Well... */
|
||||
if (! protos)
|
||||
return;
|
||||
|
||||
/* Add it... */
|
||||
protos->next = class->protocols;
|
||||
class->protocols = protos;
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/* Generic single linked list to keep various information
|
||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
Author: Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __GNU_OBJC_LIST_H
|
||||
#define __GNU_OBJC_LIST_H
|
||||
void * __objc_xrealloc (void *optr, size_t size);
|
||||
void * __objc_xmalloc (size_t size);
|
||||
|
||||
struct objc_list {
|
||||
void *head;
|
||||
struct objc_list *tail;
|
||||
};
|
||||
|
||||
/* Return a cons cell produced from (head . tail) */
|
||||
|
||||
static inline struct objc_list*
|
||||
list_cons(void* head, struct objc_list* tail)
|
||||
{
|
||||
struct objc_list* cell;
|
||||
|
||||
cell = (struct objc_list*)__objc_xmalloc(sizeof(struct objc_list));
|
||||
cell->head = head;
|
||||
cell->tail = tail;
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* Return the length of a list, list_length(NULL) returns zero */
|
||||
|
||||
static inline int
|
||||
list_length(struct objc_list* list)
|
||||
{
|
||||
int i = 0;
|
||||
while(list)
|
||||
{
|
||||
i += 1;
|
||||
list = list->tail;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Return the Nth element of LIST, where N count from zero. If N
|
||||
larger than the list length, NULL is returned */
|
||||
|
||||
static inline void*
|
||||
list_nth(int index, struct objc_list* list)
|
||||
{
|
||||
while(index-- != 0)
|
||||
{
|
||||
if(list->tail)
|
||||
list = list->tail;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return list->head;
|
||||
}
|
||||
|
||||
/* Remove the element at the head by replacing it by its successor */
|
||||
|
||||
static inline void
|
||||
list_remove_head(struct objc_list** list)
|
||||
{
|
||||
if ((*list)->tail)
|
||||
{
|
||||
struct objc_list* tail = (*list)->tail; /* fetch next */
|
||||
*(*list) = *tail; /* copy next to list head */
|
||||
free(tail); /* free next */
|
||||
}
|
||||
else /* only one element in list */
|
||||
{
|
||||
free (*list);
|
||||
(*list) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Remove the element with `car' set to ELEMENT */
|
||||
|
||||
static inline void
|
||||
list_remove_elem(struct objc_list** list, void* elem)
|
||||
{
|
||||
while (*list) {
|
||||
if ((*list)->head == elem)
|
||||
list_remove_head(list);
|
||||
list = &((*list)->tail);
|
||||
}
|
||||
}
|
||||
|
||||
/* Map FUNCTION over all elements in LIST */
|
||||
|
||||
static inline void
|
||||
list_mapcar(struct objc_list* list, void(*function)(void*))
|
||||
{
|
||||
while(list)
|
||||
{
|
||||
(*function)(list->head);
|
||||
list = list->tail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return element that has ELEM as car */
|
||||
|
||||
static inline struct objc_list**
|
||||
list_find(struct objc_list** list, void* elem)
|
||||
{
|
||||
while(*list)
|
||||
{
|
||||
if ((*list)->head == elem)
|
||||
return list;
|
||||
list = &((*list)->tail);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free list (backwards recursive) */
|
||||
|
||||
static void
|
||||
list_free(struct objc_list* list)
|
||||
{
|
||||
if(list)
|
||||
{
|
||||
list_free(list->tail);
|
||||
free(list);
|
||||
}
|
||||
}
|
||||
#endif __GNU_OBJC_LIST_H
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
# GNU Objective C Runtime Makefile for compiling with djgpp
|
||||
# Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU CC.
|
||||
#
|
||||
# GNU CC 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.
|
||||
#
|
||||
# GNU CC 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
|
||||
# GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
# Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# This Makefile is configured for GnuMAKE
|
||||
|
||||
GCC_FOR_TARGET=gcc
|
||||
|
||||
.SUFFIXES: .o .m
|
||||
|
||||
OPTIMIZE = -O2
|
||||
|
||||
# Always search these dirs when compiling.
|
||||
SUBDIR_INCLUDES = -I. -I.. -I../config
|
||||
|
||||
.c.o:
|
||||
$(GCC_FOR_TARGET) $(OPTIMIZE) \
|
||||
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
|
||||
|
||||
.m.o:
|
||||
$(GCC_FOR_TARGET) $(OPTIMIZE) -fgnu-runtime \
|
||||
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
|
||||
|
||||
OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o \
|
||||
selector.o objects.o misc.o object.o protocol.o encoding.o thread.o
|
||||
|
||||
libobjc.a: $(OBJC_O)
|
||||
-rm -f libobjc.a
|
||||
ar rc libobjc.a $(OBJC_O)
|
||||
ranlib libobjc.a
|
||||
|
||||
OBJC_H = hash.h objc-list.h sarray.h objc.h \
|
||||
objc-api.h \
|
||||
object.h protocol.h mutex.h \
|
||||
typedstream.h thread.h
|
||||
|
||||
mostlyclean:
|
||||
-rm -f *.o libobjc.a xforward fflags
|
||||
clean: mostlyclean
|
||||
distclean: mostlyclean
|
||||
extraclean: mostlyclean
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/* GNU Objective C Runtime Miscellaneous
|
||||
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#define __USE_FIXED_PROTOTYPES__
|
||||
#include <stdlib.h>
|
||||
#include "runtime.h"
|
||||
|
||||
/*
|
||||
** Error handler function
|
||||
** NULL so that default is to just print to stderr
|
||||
*/
|
||||
static objc_error_handler _objc_error_handler = NULL;
|
||||
|
||||
/* Trigger an objc error */
|
||||
void
|
||||
objc_error(id object, int code, const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
objc_verror(object, code, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Trigger an objc error */
|
||||
void
|
||||
objc_verror(id object, int code, const char* fmt, va_list ap)
|
||||
{
|
||||
BOOL result = NO;
|
||||
|
||||
/* Call the error handler if its there
|
||||
Otherwise print to stderr */
|
||||
if (_objc_error_handler)
|
||||
result = (*_objc_error_handler)(object, code, fmt, ap);
|
||||
else
|
||||
vfprintf (stderr, fmt, ap);
|
||||
|
||||
/* Continue if the error handler says its ok
|
||||
Otherwise abort the program */
|
||||
if (result)
|
||||
return;
|
||||
else
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Set the error handler */
|
||||
objc_error_handler
|
||||
objc_set_error_handler(objc_error_handler func)
|
||||
{
|
||||
objc_error_handler temp = _objc_error_handler;
|
||||
_objc_error_handler = func;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Standard functions for memory allocation and disposal.
|
||||
** Users should use these functions in their ObjC programs so
|
||||
** that they work properly with garbage collectors as well as
|
||||
** can take advantage of the exception/error handling available.
|
||||
*/
|
||||
|
||||
void *
|
||||
objc_malloc(size_t size)
|
||||
{
|
||||
void* res = (void*) (*_objc_malloc)(size);
|
||||
if(!res)
|
||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
objc_atomic_malloc(size_t size)
|
||||
{
|
||||
void* res = (void*) (*_objc_atomic_malloc)(size);
|
||||
if(!res)
|
||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
objc_valloc(size_t size)
|
||||
{
|
||||
void* res = (void*) (*_objc_valloc)(size);
|
||||
if(!res)
|
||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
objc_realloc(void *mem, size_t size)
|
||||
{
|
||||
void* res = (void*) (*_objc_realloc)(mem, size);
|
||||
if(!res)
|
||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
objc_calloc(size_t nelem, size_t size)
|
||||
{
|
||||
void* res = (void*) (*_objc_calloc)(nelem, size);
|
||||
if(!res)
|
||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
objc_free(void *mem)
|
||||
{
|
||||
(*_objc_free)(mem);
|
||||
}
|
||||
|
||||
/*
|
||||
** Hook functions for memory allocation and disposal.
|
||||
** This makes it easy to substitute garbage collection systems
|
||||
** such as Boehm's GC by assigning these function pointers
|
||||
** to the GC's allocation routines. By default these point
|
||||
** to the ANSI standard malloc, realloc, free, etc.
|
||||
**
|
||||
** Users should call the normal objc routines above for
|
||||
** memory allocation and disposal within their programs.
|
||||
*/
|
||||
void *(*_objc_malloc)(size_t) = malloc;
|
||||
void *(*_objc_atomic_malloc)(size_t) = malloc;
|
||||
void *(*_objc_valloc)(size_t) = malloc;
|
||||
void *(*_objc_realloc)(void *, size_t) = realloc;
|
||||
void *(*_objc_calloc)(size_t, size_t) = calloc;
|
||||
void (*_objc_free)(void *) = free;
|
||||
|
|
@ -1,584 +0,0 @@
|
|||
/* GNU Objective-C Runtime API.
|
||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled
|
||||
with GCC to produce an executable, this does not cause the resulting
|
||||
executable to be covered by the GNU General Public License. This
|
||||
exception does not however invalidate any other reasons why the
|
||||
executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __objc_api_INCLUDE_GNU
|
||||
#define __objc_api_INCLUDE_GNU
|
||||
|
||||
#include "objc/objc.h"
|
||||
#include "objc/hash.h"
|
||||
#include "objc/thr.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* For functions which return Method_t */
|
||||
#define METHOD_NULL (Method_t)0
|
||||
/* Boolean typedefs */
|
||||
/*
|
||||
** Method descriptor returned by introspective Object methods.
|
||||
** This is really just the first part of the more complete objc_method
|
||||
** structure defined below and used internally by the runtime.
|
||||
*/
|
||||
struct objc_method_description
|
||||
{
|
||||
SEL name; /* this is a selector, not a string */
|
||||
char *types; /* type encoding */
|
||||
};
|
||||
|
||||
/* Filer types used to describe Ivars and Methods. */
|
||||
#define _C_ID '@'
|
||||
#define _C_CLASS '#'
|
||||
#define _C_SEL ':'
|
||||
#define _C_CHR 'c'
|
||||
#define _C_UCHR 'C'
|
||||
#define _C_SHT 's'
|
||||
#define _C_USHT 'S'
|
||||
#define _C_INT 'i'
|
||||
#define _C_UINT 'I'
|
||||
#define _C_LNG 'l'
|
||||
#define _C_ULNG 'L'
|
||||
#define _C_FLT 'f'
|
||||
#define _C_DBL 'd'
|
||||
#define _C_BFLD 'b'
|
||||
#define _C_VOID 'v'
|
||||
#define _C_UNDEF '?'
|
||||
#define _C_PTR '^'
|
||||
#define _C_CHARPTR '*'
|
||||
#define _C_ATOM '%'
|
||||
#define _C_ARY_B '['
|
||||
#define _C_ARY_E ']'
|
||||
#define _C_UNION_B '('
|
||||
#define _C_UNION_E ')'
|
||||
#define _C_STRUCT_B '{'
|
||||
#define _C_STRUCT_E '}'
|
||||
|
||||
|
||||
/*
|
||||
** Error handling
|
||||
**
|
||||
** Call objc_error() or objc_verror() to record an error; this error
|
||||
** routine will generally exit the program but not necessarily if the
|
||||
** user has installed his own error handler.
|
||||
**
|
||||
** Call objc_set_error_handler to assign your own function for
|
||||
** handling errors. The function should return YES if it is ok
|
||||
** to continue execution, or return NO or just abort if the
|
||||
** program should be stopped. The default error handler is just to
|
||||
** print a message on stderr.
|
||||
**
|
||||
** The error handler function should be of type objc_error_handler
|
||||
** The first parameter is an object instance of relevance.
|
||||
** The second parameter is an error code.
|
||||
** The third parameter is a format string in the printf style.
|
||||
** The fourth parameter is a variable list of arguments.
|
||||
*/
|
||||
extern void objc_error(id object, int code, const char* fmt, ...);
|
||||
extern void objc_verror(id object, int code, const char* fmt, va_list ap);
|
||||
typedef BOOL (*objc_error_handler)(id, int code, const char *fmt, va_list ap);
|
||||
objc_error_handler objc_set_error_handler(objc_error_handler func);
|
||||
|
||||
/*
|
||||
** Error codes
|
||||
** These are used by the runtime library, and your
|
||||
** error handling may use them to determine if the error is
|
||||
** hard or soft thus whether execution can continue or abort.
|
||||
*/
|
||||
#define OBJC_ERR_UNKNOWN 0 /* Generic error */
|
||||
|
||||
#define OBJC_ERR_OBJC_VERSION 1 /* Incorrect runtime version */
|
||||
#define OBJC_ERR_GCC_VERSION 2 /* Incorrect compiler version */
|
||||
#define OBJC_ERR_MODULE_SIZE 3 /* Bad module size */
|
||||
#define OBJC_ERR_PROTOCOL_VERSION 4 /* Incorrect protocol version */
|
||||
|
||||
#define OBJC_ERR_MEMORY 10 /* Out of memory */
|
||||
|
||||
#define OBJC_ERR_RECURSE_ROOT 20 /* Attempt to archive the root
|
||||
object more than once. */
|
||||
#define OBJC_ERR_BAD_DATA 21 /* Didn't read expected data */
|
||||
#define OBJC_ERR_BAD_KEY 22 /* Bad key for object */
|
||||
#define OBJC_ERR_BAD_CLASS 23 /* Unknown class */
|
||||
#define OBJC_ERR_BAD_TYPE 24 /* Bad type specification */
|
||||
#define OBJC_ERR_NO_READ 25 /* Cannot read stream */
|
||||
#define OBJC_ERR_NO_WRITE 26 /* Cannot write stream */
|
||||
#define OBJC_ERR_STREAM_VERSION 27 /* Incorrect stream version */
|
||||
#define OBJC_ERR_BAD_OPCODE 28 /* Bad opcode */
|
||||
|
||||
#define OBJC_ERR_UNIMPLEMENTED 30 /* Method is not implemented */
|
||||
|
||||
#define OBJC_ERR_BAD_STATE 40 /* Bad thread state */
|
||||
|
||||
/*
|
||||
** Set this variable nonzero to print a line describing each
|
||||
** message that is sent. (this is currently disabled)
|
||||
*/
|
||||
extern BOOL objc_trace;
|
||||
|
||||
|
||||
/* For every class which happens to have statically allocated instances in
|
||||
this module, one OBJC_STATIC_INSTANCES is allocated by the compiler.
|
||||
INSTANCES is NULL terminated and points to all statically allocated
|
||||
instances of this class. */
|
||||
struct objc_static_instances
|
||||
{
|
||||
char *class_name;
|
||||
id instances[0];
|
||||
};
|
||||
|
||||
/*
|
||||
** Whereas a Module (defined further down) is the root (typically) of a file,
|
||||
** a Symtab is the root of the class and category definitions within the
|
||||
** module.
|
||||
**
|
||||
** A Symtab contains a variable length array of pointers to classes and
|
||||
** categories defined in the module.
|
||||
*/
|
||||
typedef struct objc_symtab {
|
||||
unsigned long sel_ref_cnt; /* Unknown. */
|
||||
SEL refs; /* Unknown. */
|
||||
unsigned short cls_def_cnt; /* Number of classes compiled
|
||||
(defined) in the module. */
|
||||
unsigned short cat_def_cnt; /* Number of categories
|
||||
compiled (defined) in the
|
||||
module. */
|
||||
|
||||
void *defs[1]; /* Variable array of pointers.
|
||||
cls_def_cnt of type Class
|
||||
followed by cat_def_cnt of
|
||||
type Category_t, followed
|
||||
by a NULL terminated array
|
||||
of objc_static_instances. */
|
||||
} Symtab, *Symtab_t;
|
||||
|
||||
|
||||
/*
|
||||
** The compiler generates one of these structures for each module that
|
||||
** composes the executable (eg main.m).
|
||||
**
|
||||
** This data structure is the root of the definition tree for the module.
|
||||
**
|
||||
** A collect program runs between ld stages and creates a ObjC ctor array.
|
||||
** That array holds a pointer to each module structure of the executable.
|
||||
*/
|
||||
typedef struct objc_module {
|
||||
unsigned long version; /* Compiler revision. */
|
||||
unsigned long size; /* sizeof(Module). */
|
||||
const char* name; /* Name of the file where the
|
||||
module was generated. The
|
||||
name includes the path. */
|
||||
|
||||
Symtab_t symtab; /* Pointer to the Symtab of
|
||||
the module. The Symtab
|
||||
holds an array of
|
||||
pointers to
|
||||
the classes and categories
|
||||
defined in the module. */
|
||||
} Module, *Module_t;
|
||||
|
||||
|
||||
/*
|
||||
** The compiler generates one of these structures for a class that has
|
||||
** instance variables defined in its specification.
|
||||
*/
|
||||
typedef struct objc_ivar* Ivar_t;
|
||||
typedef struct objc_ivar_list {
|
||||
int ivar_count; /* Number of structures (Ivar)
|
||||
contained in the list. One
|
||||
structure per instance
|
||||
variable defined in the
|
||||
class. */
|
||||
struct objc_ivar {
|
||||
const char* ivar_name; /* Name of the instance
|
||||
variable as entered in the
|
||||
class definition. */
|
||||
const char* ivar_type; /* Description of the Ivar's
|
||||
type. Useful for
|
||||
debuggers. */
|
||||
int ivar_offset; /* Byte offset from the base
|
||||
address of the instance
|
||||
structure to the variable. */
|
||||
|
||||
} ivar_list[1]; /* Variable length
|
||||
structure. */
|
||||
} IvarList, *IvarList_t;
|
||||
|
||||
|
||||
/*
|
||||
** The compiler generates one (or more) of these structures for a class that
|
||||
** has methods defined in its specification.
|
||||
**
|
||||
** The implementation of a class can be broken into separate pieces in a file
|
||||
** and categories can break them across modules. To handle this problem is a
|
||||
** singly linked list of methods.
|
||||
*/
|
||||
typedef struct objc_method Method;
|
||||
typedef Method* Method_t;
|
||||
typedef struct objc_method_list {
|
||||
struct objc_method_list* method_next; /* This variable is used to link
|
||||
a method list to another. It
|
||||
is a singly linked list. */
|
||||
int method_count; /* Number of methods defined in
|
||||
this structure. */
|
||||
struct objc_method {
|
||||
SEL method_name; /* This variable is the method's
|
||||
name. It is a char*.
|
||||
The unique integer passed to
|
||||
objc_msg_send is a char* too.
|
||||
It is compared against
|
||||
method_name using strcmp. */
|
||||
const char* method_types; /* Description of the method's
|
||||
parameter list. Useful for
|
||||
debuggers. */
|
||||
IMP method_imp; /* Address of the method in the
|
||||
executable. */
|
||||
} method_list[1]; /* Variable length
|
||||
structure. */
|
||||
} MethodList, *MethodList_t;
|
||||
|
||||
struct objc_protocol_list {
|
||||
struct objc_protocol_list *next;
|
||||
int count;
|
||||
Protocol *list[1];
|
||||
};
|
||||
|
||||
/*
|
||||
** This is used to assure consistent access to the info field of
|
||||
** classes
|
||||
*/
|
||||
#ifndef HOST_BITS_PER_LONG
|
||||
#define HOST_BITS_PER_LONG (sizeof(long)*8)
|
||||
#endif
|
||||
|
||||
#define __CLS_INFO(cls) ((cls)->info)
|
||||
#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
|
||||
#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
|
||||
|
||||
/* The structure is of type MetaClass */
|
||||
#define _CLS_META 0x2L
|
||||
#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
|
||||
|
||||
|
||||
/* The structure is of type Class */
|
||||
#define _CLS_CLASS 0x1L
|
||||
#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
|
||||
|
||||
/*
|
||||
** The class is initialized within the runtime. This means that
|
||||
** it has had correct super and sublinks assigned
|
||||
*/
|
||||
#define _CLS_RESOLV 0x8L
|
||||
#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
|
||||
#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
|
||||
|
||||
/*
|
||||
** The class has been send a +initialize message or a such is not
|
||||
** defined for this class
|
||||
*/
|
||||
#define _CLS_INITIALIZED 0x04L
|
||||
#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
|
||||
#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
|
||||
|
||||
/*
|
||||
** The class number of this class. This must be the same for both the
|
||||
** class and its meta class object
|
||||
*/
|
||||
#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
|
||||
#define CLS_SETNUMBER(cls, num) \
|
||||
({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \
|
||||
(cls)->info >>= (HOST_BITS_PER_LONG/2); \
|
||||
__CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
|
||||
|
||||
/*
|
||||
** The compiler generates one of these structures for each category. A class
|
||||
** may have many categories and contain both instance and factory methods.
|
||||
*/
|
||||
typedef struct objc_category {
|
||||
const char* category_name; /* Name of the category. Name
|
||||
contained in the () of the
|
||||
category definition. */
|
||||
const char* class_name; /* Name of the class to which
|
||||
the category belongs. */
|
||||
MethodList_t instance_methods; /* Linked list of instance
|
||||
methods defined in the
|
||||
category. NULL indicates no
|
||||
instance methods defined. */
|
||||
MethodList_t class_methods; /* Linked list of factory
|
||||
methods defined in the
|
||||
category. NULL indicates no
|
||||
class methods defined. */
|
||||
struct objc_protocol_list *protocols; /* List of Protocols
|
||||
conformed to */
|
||||
} Category, *Category_t;
|
||||
|
||||
/*
|
||||
** Structure used when a message is send to a class's super class. The
|
||||
** compiler generates one of these structures and passes it to
|
||||
** objc_msg_super.
|
||||
*/
|
||||
typedef struct objc_super {
|
||||
id self; /* Id of the object sending
|
||||
the message. */
|
||||
Class class; /* Object's super class. */
|
||||
} Super, *Super_t;
|
||||
|
||||
IMP objc_msg_lookup_super(Super_t super, SEL sel);
|
||||
|
||||
retval_t objc_msg_sendv(id, SEL, arglist_t);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** This is a hook which is called by objc_lookup_class and
|
||||
** objc_get_class if the runtime is not able to find the class.
|
||||
** This may e.g. try to load in the class using dynamic loading.
|
||||
** The function is guaranteed to be passed a non-NULL name string.
|
||||
*/
|
||||
extern Class (*_objc_lookup_class)(const char *name);
|
||||
|
||||
/*
|
||||
** This is a hook which is called by __objc_exec_class every time a class
|
||||
** or a category is loaded into the runtime. This may e.g. help a
|
||||
** dynamic loader determine the classes that have been loaded when
|
||||
** an object file is dynamically linked in.
|
||||
*/
|
||||
extern void (*_objc_load_callback)(Class class, Category* category);
|
||||
|
||||
/*
|
||||
** Hook functions for allocating, copying and disposing of instances
|
||||
*/
|
||||
extern id (*_objc_object_alloc)(Class class);
|
||||
extern id (*_objc_object_copy)(id object);
|
||||
extern id (*_objc_object_dispose)(id object);
|
||||
|
||||
/*
|
||||
** Standard functions for memory allocation and disposal.
|
||||
** Users should use these functions in their ObjC programs so
|
||||
** that they work properly with garbage collectors as well as
|
||||
** can take advantage of the exception/error handling available.
|
||||
*/
|
||||
void *
|
||||
objc_malloc(size_t size);
|
||||
|
||||
void *
|
||||
objc_atomic_malloc(size_t size);
|
||||
|
||||
void *
|
||||
objc_valloc(size_t size);
|
||||
|
||||
void *
|
||||
objc_realloc(void *mem, size_t size);
|
||||
|
||||
void *
|
||||
objc_calloc(size_t nelem, size_t size);
|
||||
|
||||
void
|
||||
objc_free(void *mem);
|
||||
|
||||
/*
|
||||
** Hook functions for memory allocation and disposal.
|
||||
** This makes it easy to substitute garbage collection systems
|
||||
** such as Boehm's GC by assigning these function pointers
|
||||
** to the GC's allocation routines. By default these point
|
||||
** to the ANSI standard malloc, realloc, free, etc.
|
||||
**
|
||||
** Users should call the normal objc routines above for
|
||||
** memory allocation and disposal within their programs.
|
||||
*/
|
||||
extern void *(*_objc_malloc)(size_t);
|
||||
extern void *(*_objc_atomic_malloc)(size_t);
|
||||
extern void *(*_objc_valloc)(size_t);
|
||||
extern void *(*_objc_realloc)(void *, size_t);
|
||||
extern void *(*_objc_calloc)(size_t, size_t);
|
||||
extern void (*_objc_free)(void *);
|
||||
|
||||
Method_t class_get_class_method(MetaClass class, SEL aSel);
|
||||
|
||||
Method_t class_get_instance_method(Class class, SEL aSel);
|
||||
|
||||
Class class_pose_as(Class impostor, Class superclass);
|
||||
|
||||
Class objc_get_class(const char *name);
|
||||
|
||||
Class objc_lookup_class(const char *name);
|
||||
|
||||
Class objc_next_class(void **enum_state);
|
||||
|
||||
const char *sel_get_name(SEL selector);
|
||||
|
||||
const char *sel_get_type(SEL selector);
|
||||
|
||||
SEL sel_get_uid(const char *name);
|
||||
|
||||
SEL sel_get_any_uid(const char *name);
|
||||
|
||||
SEL sel_get_any_typed_uid(const char *name);
|
||||
|
||||
SEL sel_get_typed_uid(const char *name, const char*);
|
||||
|
||||
SEL sel_register_name(const char *name);
|
||||
|
||||
SEL sel_register_typed_name(const char *name, const char*type);
|
||||
|
||||
|
||||
BOOL sel_is_mapped (SEL aSel);
|
||||
|
||||
extern id class_create_instance(Class class);
|
||||
|
||||
static inline const char *
|
||||
class_get_class_name(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class)?class->name:((class==Nil)?"Nil":0);
|
||||
}
|
||||
|
||||
static inline long
|
||||
class_get_instance_size(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class)?class->instance_size:0;
|
||||
}
|
||||
|
||||
static inline MetaClass
|
||||
class_get_meta_class(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class)?class->class_pointer:Nil;
|
||||
}
|
||||
|
||||
static inline Class
|
||||
class_get_super_class(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class)?class->super_class:Nil;
|
||||
}
|
||||
|
||||
static inline int
|
||||
class_get_version(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class)?class->version:-1;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
class_is_class(Class class)
|
||||
{
|
||||
return CLS_ISCLASS(class);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
class_is_meta_class(Class class)
|
||||
{
|
||||
return CLS_ISMETA(class);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
class_set_version(Class class, long version)
|
||||
{
|
||||
if (CLS_ISCLASS(class))
|
||||
class->version = version;
|
||||
}
|
||||
|
||||
static inline IMP
|
||||
method_get_imp(Method_t method)
|
||||
{
|
||||
return (method!=METHOD_NULL)?method->method_imp:(IMP)0;
|
||||
}
|
||||
|
||||
IMP get_imp (Class class, SEL sel);
|
||||
|
||||
/* Redefine on NeXTSTEP so as not to conflict with system function */
|
||||
#ifdef __NeXT__
|
||||
#define object_copy gnu_object_copy
|
||||
#define object_dispose gnu_object_dispose
|
||||
#endif
|
||||
|
||||
id object_copy(id object);
|
||||
|
||||
id object_dispose(id object);
|
||||
|
||||
static inline Class
|
||||
object_get_class(id object)
|
||||
{
|
||||
return ((object!=nil)
|
||||
? (CLS_ISCLASS(object->class_pointer)
|
||||
? object->class_pointer
|
||||
: (CLS_ISMETA(object->class_pointer)
|
||||
? (Class)object
|
||||
: Nil))
|
||||
: Nil);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
object_get_class_name(id object)
|
||||
{
|
||||
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
|
||||
?object->class_pointer->name
|
||||
:((Class)object)->name)
|
||||
:"Nil");
|
||||
}
|
||||
|
||||
static inline MetaClass
|
||||
object_get_meta_class(id object)
|
||||
{
|
||||
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
|
||||
?object->class_pointer->class_pointer
|
||||
:(CLS_ISMETA(object->class_pointer)
|
||||
?object->class_pointer
|
||||
:Nil))
|
||||
:Nil);
|
||||
}
|
||||
|
||||
static inline Class
|
||||
object_get_super_class
|
||||
(id object)
|
||||
{
|
||||
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
|
||||
?object->class_pointer->super_class
|
||||
:(CLS_ISMETA(object->class_pointer)
|
||||
?((Class)object)->super_class
|
||||
:Nil))
|
||||
:Nil);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
object_is_class(id object)
|
||||
{
|
||||
return CLS_ISCLASS((Class)object);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
object_is_instance(id object)
|
||||
{
|
||||
return (object!=nil)&&CLS_ISCLASS(object->class_pointer);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
object_is_meta_class(id object)
|
||||
{
|
||||
return CLS_ISMETA((Class)object);
|
||||
}
|
||||
|
||||
struct sarray*
|
||||
objc_get_uninstalled_dtable(void);
|
||||
|
||||
#endif /* not __objc_api_INCLUDE_GNU */
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
/* Basic data types for Objective C.
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __objc_INCLUDE_GNU
|
||||
#define __objc_INCLUDE_GNU
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
** Definition of the boolean type.
|
||||
*/
|
||||
#ifdef __vxworks
|
||||
typedef int BOOL;
|
||||
#else
|
||||
typedef unsigned char BOOL;
|
||||
#endif
|
||||
#define YES (BOOL)1
|
||||
#define NO (BOOL)0
|
||||
|
||||
/*
|
||||
** Definition of a selector. Selectors themselves are not unique, but
|
||||
** the sel_id is a unique identifier.
|
||||
*/
|
||||
typedef const struct objc_selector
|
||||
{
|
||||
void *sel_id;
|
||||
const char *sel_types;
|
||||
} *SEL;
|
||||
|
||||
inline static BOOL
|
||||
sel_eq (SEL s1, SEL s2)
|
||||
{
|
||||
if (s1 == 0 || s2 == 0)
|
||||
return s1 == s2;
|
||||
else
|
||||
return s1->sel_id == s2->sel_id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** ObjC uses this typedef for untyped instances.
|
||||
*/
|
||||
typedef struct objc_object {
|
||||
struct objc_class* class_pointer;
|
||||
} *id;
|
||||
|
||||
/*
|
||||
** Definition of method type. When retrieving the implementation of a
|
||||
** method, this is type of the pointer returned
|
||||
*/
|
||||
typedef id (*IMP)(id, SEL, ...);
|
||||
|
||||
/*
|
||||
** More simple types...
|
||||
*/
|
||||
#define nil (id)0 /* id of Nil instance */
|
||||
#define Nil (Class)0 /* id of Nil class */
|
||||
typedef char *STR; /* String alias */
|
||||
|
||||
/*
|
||||
** The compiler generates one of these structures for each class.
|
||||
**
|
||||
** This structure is the definition for classes.
|
||||
**
|
||||
** This structure is generated by the compiler in the executable and used by
|
||||
** the run-time during normal messaging operations. Therefore some members
|
||||
** change type. The compiler generates "char* const" and places a string in
|
||||
** the following member variables: super_class.
|
||||
*/
|
||||
typedef struct objc_class *MetaClass;
|
||||
typedef struct objc_class *Class;
|
||||
struct objc_class {
|
||||
MetaClass class_pointer; /* Pointer to the class's
|
||||
meta class. */
|
||||
struct objc_class* super_class; /* Pointer to the super
|
||||
class. NULL for class
|
||||
Object. */
|
||||
const char* name; /* Name of the class. */
|
||||
long version; /* Unknown. */
|
||||
unsigned long info; /* Bit mask. See class masks
|
||||
defined above. */
|
||||
long instance_size; /* Size in bytes of the class.
|
||||
The sum of the class
|
||||
definition and all super
|
||||
class definitions. */
|
||||
struct objc_ivar_list* ivars; /* Pointer to a structure that
|
||||
describes the instance
|
||||
variables in the class
|
||||
definition. NULL indicates
|
||||
no instance variables. Does
|
||||
not include super class
|
||||
variables. */
|
||||
struct objc_method_list* methods; /* Linked list of instance
|
||||
methods defined for the
|
||||
class. */
|
||||
struct sarray * dtable; /* Pointer to instance
|
||||
method dispatch table. */
|
||||
struct objc_class* subclass_list; /* Subclasses */
|
||||
struct objc_class* sibling_class;
|
||||
|
||||
struct objc_protocol_list *protocols; /* Protocols conformed to */
|
||||
};
|
||||
|
||||
#ifndef __OBJC__
|
||||
typedef struct objc_protocol {
|
||||
struct objc_class* class_pointer;
|
||||
char *protocol_name;
|
||||
struct objc_protocol_list *protocol_list;
|
||||
struct objc_method_description_list *instance_methods, *class_methods;
|
||||
} Protocol;
|
||||
|
||||
#else /* __OBJC__ */
|
||||
@class Protocol;
|
||||
#endif
|
||||
|
||||
typedef void* retval_t; /* return value */
|
||||
typedef void(*apply_t)(void); /* function pointer */
|
||||
typedef union {
|
||||
char *arg_ptr;
|
||||
char arg_regs[sizeof (char*)];
|
||||
} *arglist_t; /* argument frame */
|
||||
|
||||
|
||||
IMP objc_msg_lookup(id receiver, SEL op);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not __objc_INCLUDE_GNU */
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/* GNU Objective C Runtime class related functions
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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
|
||||
GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#include "../tconfig.h" /* include defs of bzero for target */
|
||||
#include "runtime.h" /* the kitchen sink */
|
||||
|
||||
id __objc_object_alloc(Class);
|
||||
id __objc_object_dispose(id);
|
||||
id __objc_object_copy(id);
|
||||
|
||||
id (*_objc_object_alloc)(Class) = __objc_object_alloc; /* !T:SINGLE */
|
||||
id (*_objc_object_dispose)(id) = __objc_object_dispose; /* !T:SINGLE */
|
||||
id (*_objc_object_copy)(id) = __objc_object_copy; /* !T:SINGLE */
|
||||
|
||||
id
|
||||
class_create_instance(Class class)
|
||||
{
|
||||
id new = nil;
|
||||
if (CLS_ISCLASS(class))
|
||||
new = (*_objc_object_alloc)(class);
|
||||
if (new!=nil)
|
||||
{
|
||||
memset (new, 0, class->instance_size);
|
||||
new->class_pointer = class;
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
id
|
||||
object_copy(id object)
|
||||
{
|
||||
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
|
||||
return (*_objc_object_copy)(object);
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
id
|
||||
object_dispose(id object)
|
||||
{
|
||||
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
|
||||
{
|
||||
if (_objc_object_dispose)
|
||||
(*_objc_object_dispose)(object);
|
||||
else
|
||||
objc_free(object);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
id __objc_object_alloc(Class class)
|
||||
{
|
||||
return (id)objc_malloc(class->instance_size);
|
||||
}
|
||||
|
||||
id __objc_object_dispose(id object)
|
||||
{
|
||||
objc_free(object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
id __objc_object_copy(id object)
|
||||
{
|
||||
id copy = class_create_instance(object->class_pointer);
|
||||
memcpy(copy, object, object->class_pointer->instance_size);
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/* GNU Objective C Runtime internal declarations
|
||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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
|
||||
GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __objc_runtime_INCLUDE_GNU
|
||||
#define __objc_runtime_INCLUDE_GNU
|
||||
|
||||
#include <stdarg.h> /* for varargs and va_list's */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stddef.h> /* so noone else will get system versions */
|
||||
#include "assert.h"
|
||||
|
||||
#include "objc/objc.h" /* core data types */
|
||||
#include "objc/objc-api.h" /* runtime api functions */
|
||||
|
||||
#include "objc/thr.h" /* thread and mutex support */
|
||||
|
||||
#include "objc/hash.h" /* hash structures */
|
||||
#include "objc/objc-list.h" /* linear lists */
|
||||
|
||||
extern void __objc_add_class_to_hash(Class); /* (objc-class.c) */
|
||||
extern void __objc_init_selector_tables(void); /* (objc-sel.c) */
|
||||
extern void __objc_init_class_tables(void); /* (objc-class.c) */
|
||||
extern void __objc_init_dispatch_tables(void); /* (objc-dispatch.c) */
|
||||
extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
|
||||
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
|
||||
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
|
||||
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
|
||||
|
||||
extern int __objc_init_thread_system(void); /* thread.c */
|
||||
extern int __objc_fini_thread_system(void); /* thread.c */
|
||||
extern void __objc_print_dtable_stats(void); /* sendmsg.c */
|
||||
|
||||
extern void class_add_method_list(Class, MethodList_t);
|
||||
|
||||
/* Registering instance methods as class methods for root classes */
|
||||
extern void __objc_register_instance_methods_to_class(Class);
|
||||
extern Method_t search_for_method_in_list(MethodList_t list, SEL op);
|
||||
|
||||
/* True when class links has been resolved */
|
||||
extern BOOL __objc_class_links_resolved;
|
||||
|
||||
/* Number of selectors stored in each of the selector tables */
|
||||
extern int __objc_selector_max_index;
|
||||
|
||||
/* Mutex locking __objc_selector_max_index and its arrays. */
|
||||
extern objc_mutex_t __objc_runtime_mutex;
|
||||
|
||||
/* Number of threads which are alive. */
|
||||
extern int __objc_runtime_threads_alive;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_PRINTF(format, args...) printf (format, ## args)
|
||||
#else
|
||||
#define DEBUG_PRINTF(format, args...)
|
||||
#endif
|
||||
|
||||
BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */
|
||||
SEL __sel_register_typed_name (const char*, const char*,
|
||||
struct objc_selector*, BOOL is_const);
|
||||
|
||||
#endif /* not __objc_runtime_INCLUDE_GNU */
|
||||
|
||||
|
||||
|
|
@ -1,522 +0,0 @@
|
|||
/* Sparse Arrays for Objective C dispatch tables
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#include "objc/sarray.h"
|
||||
#include "objc/runtime.h"
|
||||
#include <stdio.h>
|
||||
#include "assert.h"
|
||||
|
||||
int nbuckets = 0; /* !T:MUTEX */
|
||||
int nindices = 0; /* !T:MUTEX */
|
||||
int narrays = 0; /* !T:MUTEX */
|
||||
int idxsize = 0; /* !T:MUTEX */
|
||||
|
||||
static void * first_free_data = NULL; /* !T:MUTEX */
|
||||
|
||||
#ifdef OBJC_SPARSE2
|
||||
const char* __objc_sparse2_id = "2 level sparse indices";
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
const char* __objc_sparse3_id = "3 level sparse indices";
|
||||
#endif
|
||||
|
||||
#ifdef __alpha__
|
||||
const void *memcpy (void*, const void*, size_t);
|
||||
#endif
|
||||
|
||||
/* This function removes any structures left over from free operations
|
||||
that were not safe in a multi-threaded environment. */
|
||||
void
|
||||
sarray_remove_garbage(void)
|
||||
{
|
||||
void **vp;
|
||||
void *np;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
vp = first_free_data;
|
||||
first_free_data = NULL;
|
||||
|
||||
while (vp) {
|
||||
np = *vp;
|
||||
objc_free(vp);
|
||||
vp = np;
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* Free a block of dynamically allocated memory. If we are in multi-threaded
|
||||
mode, it is ok to free it. If not, we add it to the garbage heap to be
|
||||
freed later. */
|
||||
|
||||
static void
|
||||
sarray_free_garbage(void *vp)
|
||||
{
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
if (__objc_runtime_threads_alive == 1) {
|
||||
objc_free(vp);
|
||||
if (first_free_data)
|
||||
sarray_remove_garbage();
|
||||
}
|
||||
else {
|
||||
*(void **)vp = first_free_data;
|
||||
first_free_data = vp;
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* sarray_at_put : copies data in such a way as to be thread reader safe. */
|
||||
void
|
||||
sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||
{
|
||||
#ifdef OBJC_SPARSE3
|
||||
struct sindex** the_index;
|
||||
struct sindex* new_index;
|
||||
#endif
|
||||
struct sbucket** the_bucket;
|
||||
struct sbucket* new_bucket;
|
||||
#ifdef OBJC_SPARSE3
|
||||
size_t ioffset;
|
||||
#endif
|
||||
size_t boffset;
|
||||
size_t eoffset;
|
||||
#ifdef PRECOMPUTE_SELECTORS
|
||||
union sofftype xx;
|
||||
xx.idx = index;
|
||||
#ifdef OBJC_SPARSE3
|
||||
ioffset = xx.off.ioffset;
|
||||
#endif
|
||||
boffset = xx.off.boffset;
|
||||
eoffset = xx.off.eoffset;
|
||||
#else /* not PRECOMPUTE_SELECTORS */
|
||||
#ifdef OBJC_SPARSE3
|
||||
ioffset = index/INDEX_CAPACITY;
|
||||
boffset = (index/BUCKET_SIZE)%INDEX_SIZE;
|
||||
eoffset = index%BUCKET_SIZE;
|
||||
#else
|
||||
boffset = index/BUCKET_SIZE;
|
||||
eoffset = index%BUCKET_SIZE;
|
||||
#endif
|
||||
#endif /* not PRECOMPUTE_SELECTORS */
|
||||
|
||||
assert(soffset_decode(index) < array->capacity); /* Range check */
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
the_index = &(array->indices[ioffset]);
|
||||
the_bucket = &((*the_index)->buckets[boffset]);
|
||||
#else
|
||||
the_bucket = &(array->buckets[boffset]);
|
||||
#endif
|
||||
|
||||
if ((*the_bucket)->elems[eoffset] == element)
|
||||
return; /* great! we just avoided a lazy copy */
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
|
||||
/* First, perform lazy copy/allocation of index if needed */
|
||||
|
||||
if ((*the_index) == array->empty_index) {
|
||||
|
||||
/* The index was previously empty, allocate a new */
|
||||
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
|
||||
memcpy(new_index, array->empty_index, sizeof(struct sindex));
|
||||
new_index->version.version = array->version.version;
|
||||
*the_index = new_index; /* Prepared for install. */
|
||||
the_bucket = &((*the_index)->buckets[boffset]);
|
||||
|
||||
nindices += 1;
|
||||
} else if ((*the_index)->version.version != array->version.version) {
|
||||
|
||||
/* This index must be lazy copied */
|
||||
struct sindex* old_index = *the_index;
|
||||
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
|
||||
memcpy( new_index, old_index, sizeof(struct sindex));
|
||||
new_index->version.version = array->version.version;
|
||||
*the_index = new_index; /* Prepared for install. */
|
||||
the_bucket = &((*the_index)->buckets[boffset]);
|
||||
|
||||
nindices += 1;
|
||||
}
|
||||
|
||||
#endif /* OBJC_SPARSE3 */
|
||||
|
||||
/* next, perform lazy allocation/copy of the bucket if needed */
|
||||
|
||||
if ((*the_bucket) == array->empty_bucket) {
|
||||
|
||||
/* The bucket was previously empty (or something like that), */
|
||||
/* allocate a new. This is the effect of `lazy' allocation */
|
||||
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
|
||||
memcpy((void *) new_bucket, (const void*)array->empty_bucket,
|
||||
sizeof(struct sbucket));
|
||||
new_bucket->version.version = array->version.version;
|
||||
*the_bucket = new_bucket; /* Prepared for install. */
|
||||
|
||||
nbuckets += 1;
|
||||
|
||||
} else if ((*the_bucket)->version.version != array->version.version) {
|
||||
|
||||
/* Perform lazy copy. */
|
||||
struct sbucket* old_bucket = *the_bucket;
|
||||
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
|
||||
memcpy( new_bucket, old_bucket, sizeof(struct sbucket));
|
||||
new_bucket->version.version = array->version.version;
|
||||
*the_bucket = new_bucket; /* Prepared for install. */
|
||||
|
||||
nbuckets += 1;
|
||||
|
||||
}
|
||||
(*the_bucket)->elems[eoffset] = element;
|
||||
}
|
||||
|
||||
void
|
||||
sarray_at_put_safe(struct sarray* array, sidx index, void* element)
|
||||
{
|
||||
if(soffset_decode(index) >= array->capacity)
|
||||
sarray_realloc(array, soffset_decode(index)+1);
|
||||
sarray_at_put(array, index, element);
|
||||
}
|
||||
|
||||
struct sarray*
|
||||
sarray_new (int size, void* default_element)
|
||||
{
|
||||
struct sarray* arr;
|
||||
#ifdef OBJC_SPARSE3
|
||||
size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1;
|
||||
struct sindex ** new_indices;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
size_t num_indices = ((size-1)/BUCKET_SIZE)+1;
|
||||
struct sbucket ** new_buckets;
|
||||
#endif
|
||||
int counter;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
/* Allocate core array */
|
||||
arr = (struct sarray*) objc_malloc(sizeof(struct sarray));
|
||||
arr->version.version = 0;
|
||||
|
||||
/* Initialize members */
|
||||
#ifdef OBJC_SPARSE3
|
||||
arr->capacity = num_indices*INDEX_CAPACITY;
|
||||
new_indices = (struct sindex**)
|
||||
objc_malloc(sizeof(struct sindex*)*num_indices);
|
||||
|
||||
arr->empty_index = (struct sindex*) objc_malloc(sizeof(struct sindex));
|
||||
arr->empty_index->version.version = 0;
|
||||
|
||||
narrays += 1;
|
||||
idxsize += num_indices;
|
||||
nindices += 1;
|
||||
|
||||
#else /* OBJC_SPARSE2 */
|
||||
arr->capacity = num_indices*BUCKET_SIZE;
|
||||
new_buckets = (struct sbucket**)
|
||||
objc_malloc(sizeof(struct sbucket*)*num_indices);
|
||||
|
||||
narrays += 1;
|
||||
idxsize += num_indices;
|
||||
|
||||
#endif
|
||||
|
||||
arr->empty_bucket = (struct sbucket*) objc_malloc(sizeof(struct sbucket));
|
||||
arr->empty_bucket->version.version = 0;
|
||||
|
||||
nbuckets += 1;
|
||||
|
||||
arr->ref_count = 1;
|
||||
arr->is_copy_of = (struct sarray*)0;
|
||||
|
||||
for (counter=0; counter<BUCKET_SIZE; counter++)
|
||||
arr->empty_bucket->elems[counter] = default_element;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
for (counter=0; counter<INDEX_SIZE; counter++)
|
||||
arr->empty_index->buckets[counter] = arr->empty_bucket;
|
||||
|
||||
for (counter=0; counter<num_indices; counter++)
|
||||
new_indices[counter] = arr->empty_index;
|
||||
|
||||
#else /* OBJC_SPARSE2 */
|
||||
|
||||
for (counter=0; counter<num_indices; counter++)
|
||||
new_buckets[counter] = arr->empty_bucket;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
arr->indices = new_indices;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
arr->buckets = new_buckets;
|
||||
#endif
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
/* Reallocate the sparse array to hold `newsize' entries
|
||||
Note: We really allocate and then free. We have to do this to ensure that
|
||||
any concurrent readers notice the update. */
|
||||
|
||||
void
|
||||
sarray_realloc(struct sarray* array, int newsize)
|
||||
{
|
||||
#ifdef OBJC_SPARSE3
|
||||
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY;
|
||||
size_t new_max_index = ((newsize-1)/INDEX_CAPACITY);
|
||||
size_t rounded_size = (new_max_index+1)*INDEX_CAPACITY;
|
||||
|
||||
struct sindex ** new_indices;
|
||||
struct sindex ** old_indices;
|
||||
|
||||
#else /* OBJC_SPARSE2 */
|
||||
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
|
||||
size_t new_max_index = ((newsize-1)/BUCKET_SIZE);
|
||||
size_t rounded_size = (new_max_index+1)*BUCKET_SIZE;
|
||||
|
||||
struct sbucket ** new_buckets;
|
||||
struct sbucket ** old_buckets;
|
||||
|
||||
#endif
|
||||
|
||||
int counter;
|
||||
|
||||
assert(newsize > 0);
|
||||
|
||||
/* The size is the same, just ignore the request */
|
||||
if(rounded_size <= array->capacity)
|
||||
return;
|
||||
|
||||
assert(array->ref_count == 1); /* stop if lazy copied... */
|
||||
|
||||
/* We are asked to extend the array -- allocate new bucket table, */
|
||||
/* and insert empty_bucket in newly allocated places. */
|
||||
if(rounded_size > array->capacity)
|
||||
{
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
new_max_index += 4;
|
||||
rounded_size = (new_max_index+1)*INDEX_CAPACITY;
|
||||
|
||||
#else /* OBJC_SPARSE2 */
|
||||
new_max_index += 4;
|
||||
rounded_size = (new_max_index+1)*BUCKET_SIZE;
|
||||
#endif
|
||||
|
||||
/* update capacity */
|
||||
array->capacity = rounded_size;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* alloc to force re-read by any concurrent readers. */
|
||||
old_indices = array->indices;
|
||||
new_indices = (struct sindex**)
|
||||
objc_malloc((new_max_index+1)*sizeof(struct sindex*));
|
||||
#else /* OBJC_SPARSE2 */
|
||||
old_buckets = array->buckets;
|
||||
new_buckets = (struct sbucket**)
|
||||
objc_malloc((new_max_index+1)*sizeof(struct sbucket*));
|
||||
#endif
|
||||
|
||||
/* copy buckets below old_max_index (they are still valid) */
|
||||
for(counter = 0; counter <= old_max_index; counter++ ) {
|
||||
#ifdef OBJC_SPARSE3
|
||||
new_indices[counter] = old_indices[counter];
|
||||
#else /* OBJC_SPARSE2 */
|
||||
new_buckets[counter] = old_buckets[counter];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* reset entries above old_max_index to empty_bucket */
|
||||
for(counter = old_max_index+1; counter <= new_max_index; counter++)
|
||||
new_indices[counter] = array->empty_index;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
/* reset entries above old_max_index to empty_bucket */
|
||||
for(counter = old_max_index+1; counter <= new_max_index; counter++)
|
||||
new_buckets[counter] = array->empty_bucket;
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* install the new indices */
|
||||
array->indices = new_indices;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
array->buckets = new_buckets;
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* free the old indices */
|
||||
sarray_free_garbage(old_indices);
|
||||
#else /* OBJC_SPARSE2 */
|
||||
sarray_free_garbage(old_buckets);
|
||||
#endif
|
||||
|
||||
idxsize += (new_max_index-old_max_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Free a sparse array allocated with sarray_new */
|
||||
|
||||
void
|
||||
sarray_free(struct sarray* array) {
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY;
|
||||
struct sindex ** old_indices;
|
||||
#else
|
||||
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
|
||||
struct sbucket ** old_buckets;
|
||||
#endif
|
||||
int counter = 0;
|
||||
|
||||
assert(array->ref_count != 0); /* Freed multiple times!!! */
|
||||
|
||||
if(--(array->ref_count) != 0) /* There exists copies of me */
|
||||
return;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
old_indices = array->indices;
|
||||
#else
|
||||
old_buckets = array->buckets;
|
||||
#endif
|
||||
|
||||
if((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
|
||||
sarray_free(array->is_copy_of);
|
||||
|
||||
/* Free all entries that do not point to empty_bucket */
|
||||
for(counter = 0; counter <= old_max_index; counter++ ) {
|
||||
#ifdef OBJC_SPARSE3
|
||||
struct sindex* idx = old_indices[counter];
|
||||
if((idx != array->empty_index) &&
|
||||
(idx->version.version == array->version.version)) {
|
||||
int c2;
|
||||
for(c2=0; c2<INDEX_SIZE; c2++) {
|
||||
struct sbucket* bkt = idx->buckets[c2];
|
||||
if((bkt != array->empty_bucket) &&
|
||||
(bkt->version.version == array->version.version))
|
||||
{
|
||||
sarray_free_garbage(bkt);
|
||||
nbuckets -= 1;
|
||||
}
|
||||
}
|
||||
sarray_free_garbage(idx);
|
||||
nindices -= 1;
|
||||
}
|
||||
#else /* OBJC_SPARSE2 */
|
||||
struct sbucket* bkt = array->buckets[counter];
|
||||
if ((bkt != array->empty_bucket) &&
|
||||
(bkt->version.version == array->version.version))
|
||||
{
|
||||
sarray_free_garbage(bkt);
|
||||
nbuckets -= 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* free empty_index */
|
||||
if(array->empty_index->version.version == array->version.version) {
|
||||
sarray_free_garbage(array->empty_index);
|
||||
nindices -= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* free empty_bucket */
|
||||
if(array->empty_bucket->version.version == array->version.version) {
|
||||
sarray_free_garbage(array->empty_bucket);
|
||||
nbuckets -= 1;
|
||||
}
|
||||
idxsize -= (old_max_index+1);
|
||||
narrays -= 1;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* free bucket table */
|
||||
sarray_free_garbage(array->indices);
|
||||
|
||||
#else
|
||||
/* free bucket table */
|
||||
sarray_free_garbage(array->buckets);
|
||||
|
||||
#endif
|
||||
|
||||
/* free array */
|
||||
sarray_free_garbage(array);
|
||||
}
|
||||
|
||||
/* This is a lazy copy. Only the core of the structure is actually */
|
||||
/* copied. */
|
||||
|
||||
struct sarray*
|
||||
sarray_lazy_copy(struct sarray* oarr)
|
||||
{
|
||||
struct sarray* arr;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1;
|
||||
struct sindex ** new_indices;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1;
|
||||
struct sbucket ** new_buckets;
|
||||
#endif
|
||||
|
||||
/* Allocate core array */
|
||||
arr = (struct sarray*) objc_malloc(sizeof(struct sarray)); /* !!! */
|
||||
arr->version.version = oarr->version.version + 1;
|
||||
#ifdef OBJC_SPARSE3
|
||||
arr->empty_index = oarr->empty_index;
|
||||
#endif
|
||||
arr->empty_bucket = oarr->empty_bucket;
|
||||
arr->ref_count = 1;
|
||||
oarr->ref_count += 1;
|
||||
arr->is_copy_of = oarr;
|
||||
arr->capacity = oarr->capacity;
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
/* Copy bucket table */
|
||||
new_indices = (struct sindex**)
|
||||
objc_malloc(sizeof(struct sindex*)*num_indices);
|
||||
memcpy( new_indices,oarr->indices,
|
||||
sizeof(struct sindex*)*num_indices);
|
||||
arr->indices = new_indices;
|
||||
#else
|
||||
/* Copy bucket table */
|
||||
new_buckets = (struct sbucket**)
|
||||
objc_malloc(sizeof(struct sbucket*)*num_indices);
|
||||
memcpy( new_buckets,oarr->buckets,
|
||||
sizeof(struct sbucket*)*num_indices);
|
||||
arr->buckets = new_buckets;
|
||||
#endif
|
||||
|
||||
idxsize += num_indices;
|
||||
narrays += 1;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
/* Sparse Arrays for Objective C dispatch tables
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files
|
||||
compiled with GCC to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __sarray_INCLUDE_GNU
|
||||
#define __sarray_INCLUDE_GNU
|
||||
|
||||
#define OBJC_SPARSE2 /* 2-level sparse array */
|
||||
/* #define OBJC_SPARSE3 */ /* 3-level sparse array */
|
||||
|
||||
#ifdef OBJC_SPARSE2
|
||||
extern const char* __objc_sparse2_id;
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
extern const char* __objc_sparse3_id;
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "objc/thr.h"
|
||||
|
||||
extern int nbuckets; /* for stats */
|
||||
extern int nindices;
|
||||
extern int narrays;
|
||||
extern int idxsize;
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* An unsigned integer of same size as a pointer */
|
||||
#define SIZET_BITS (sizeof(size_t)*8)
|
||||
|
||||
#if defined(__sparc__) || defined(OBJC_SPARSE2)
|
||||
#define PRECOMPUTE_SELECTORS
|
||||
#endif
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
|
||||
/* Buckets are 8 words each */
|
||||
#define BUCKET_BITS 3
|
||||
#define BUCKET_SIZE (1<<BUCKET_BITS)
|
||||
#define BUCKET_MASK (BUCKET_SIZE-1)
|
||||
|
||||
/* Indices are 16 words each */
|
||||
#define INDEX_BITS 4
|
||||
#define INDEX_SIZE (1<<INDEX_BITS)
|
||||
#define INDEX_MASK (INDEX_SIZE-1)
|
||||
|
||||
#define INDEX_CAPACITY (BUCKET_SIZE*INDEX_SIZE)
|
||||
|
||||
#else /* OBJC_SPARSE2 */
|
||||
|
||||
/* Buckets are 32 words each */
|
||||
#define BUCKET_BITS 5
|
||||
#define BUCKET_SIZE (1<<BUCKET_BITS)
|
||||
#define BUCKET_MASK (BUCKET_SIZE-1)
|
||||
|
||||
#endif /* OBJC_SPARSE2 */
|
||||
|
||||
typedef size_t sidx;
|
||||
|
||||
#ifdef PRECOMPUTE_SELECTORS
|
||||
|
||||
struct soffset {
|
||||
#ifdef OBJC_SPARSE3
|
||||
unsigned int unused : SIZET_BITS/4;
|
||||
unsigned int eoffset : SIZET_BITS/4;
|
||||
unsigned int boffset : SIZET_BITS/4;
|
||||
unsigned int ioffset : SIZET_BITS/4;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
#ifdef __sparc__
|
||||
unsigned int boffset : (SIZET_BITS - 2) - BUCKET_BITS;
|
||||
unsigned int eoffset : BUCKET_BITS;
|
||||
unsigned int unused : 2;
|
||||
#else
|
||||
unsigned int boffset : SIZET_BITS/2;
|
||||
unsigned int eoffset : SIZET_BITS/2;
|
||||
#endif
|
||||
#endif /* OBJC_SPARSE2 */
|
||||
};
|
||||
|
||||
union sofftype {
|
||||
struct soffset off;
|
||||
sidx idx;
|
||||
};
|
||||
|
||||
#endif /* not PRECOMPUTE_SELECTORS */
|
||||
|
||||
union sversion {
|
||||
int version;
|
||||
void *next_free;
|
||||
};
|
||||
|
||||
struct sbucket {
|
||||
void* elems[BUCKET_SIZE]; /* elements stored in array */
|
||||
union sversion version; /* used for copy-on-write */
|
||||
};
|
||||
|
||||
#ifdef OBJC_SPARSE3
|
||||
|
||||
struct sindex {
|
||||
struct sbucket* buckets[INDEX_SIZE];
|
||||
union sversion version; /* used for copy-on-write */
|
||||
};
|
||||
|
||||
#endif /* OBJC_SPARSE3 */
|
||||
|
||||
struct sarray {
|
||||
#ifdef OBJC_SPARSE3
|
||||
struct sindex** indices;
|
||||
struct sindex* empty_index;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
struct sbucket** buckets;
|
||||
#endif /* OBJC_SPARSE2 */
|
||||
struct sbucket* empty_bucket;
|
||||
union sversion version; /* used for copy-on-write */
|
||||
short ref_count;
|
||||
struct sarray* is_copy_of;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
struct sarray* sarray_new(int, void* default_element);
|
||||
void sarray_free(struct sarray*);
|
||||
struct sarray* sarray_lazy_copy(struct sarray*);
|
||||
void sarray_realloc(struct sarray*, int new_size);
|
||||
void sarray_at_put(struct sarray*, sidx index, void* elem);
|
||||
void sarray_at_put_safe(struct sarray*, sidx index, void* elem);
|
||||
|
||||
struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */
|
||||
void sarray_remove_garbage(void);
|
||||
|
||||
|
||||
#ifdef PRECOMPUTE_SELECTORS
|
||||
/* Transform soffset values to ints and vica verca */
|
||||
static inline unsigned int
|
||||
soffset_decode(sidx index)
|
||||
{
|
||||
union sofftype x;
|
||||
x.idx = index;
|
||||
#ifdef OBJC_SPARSE3
|
||||
return x.off.eoffset
|
||||
+ (x.off.boffset*BUCKET_SIZE)
|
||||
+ (x.off.ioffset*INDEX_CAPACITY);
|
||||
#else /* OBJC_SPARSE2 */
|
||||
return x.off.eoffset + (x.off.boffset*BUCKET_SIZE);
|
||||
#endif /* OBJC_SPARSE2 */
|
||||
}
|
||||
|
||||
static inline sidx
|
||||
soffset_encode(size_t offset)
|
||||
{
|
||||
union sofftype x;
|
||||
x.off.eoffset = offset%BUCKET_SIZE;
|
||||
#ifdef OBJC_SPARSE3
|
||||
x.off.boffset = (offset/BUCKET_SIZE)%INDEX_SIZE;
|
||||
x.off.ioffset = offset/INDEX_CAPACITY;
|
||||
#else /* OBJC_SPARSE2 */
|
||||
x.off.boffset = offset/BUCKET_SIZE;
|
||||
#endif
|
||||
return (sidx)x.idx;
|
||||
}
|
||||
|
||||
#else /* not PRECOMPUTE_SELECTORS */
|
||||
|
||||
static inline size_t
|
||||
soffset_decode(sidx index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
static inline sidx
|
||||
soffset_encode(size_t offset)
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
#endif /* not PRECOMPUTE_SELECTORS */
|
||||
|
||||
/* Get element from the Sparse array `array' at offset `index' */
|
||||
|
||||
static inline void* sarray_get(struct sarray* array, sidx index)
|
||||
{
|
||||
#ifdef PRECOMPUTE_SELECTORS
|
||||
union sofftype x;
|
||||
x.idx = index;
|
||||
#ifdef OBJC_SPARSE3
|
||||
return
|
||||
array->
|
||||
indices[x.off.ioffset]->
|
||||
buckets[x.off.boffset]->
|
||||
elems[x.off.eoffset];
|
||||
#else /* OBJC_SPARSE2 */
|
||||
return array->buckets[x.off.boffset]->elems[x.off.eoffset];
|
||||
#endif /* OBJC_SPARSE2 */
|
||||
#else /* not PRECOMPUTE_SELECTORS */
|
||||
#ifdef OBJC_SPARSE3
|
||||
return array->
|
||||
indices[index/INDEX_CAPACITY]->
|
||||
buckets[(index/BUCKET_SIZE)%INDEX_SIZE]->
|
||||
elems[index%BUCKET_SIZE];
|
||||
#else /* OBJC_SPARSE2 */
|
||||
return array->buckets[index/BUCKET_SIZE]->elems[index%BUCKET_SIZE];
|
||||
#endif /* not OBJC_SPARSE3 */
|
||||
#endif /* not PRECOMPUTE_SELECTORS */
|
||||
}
|
||||
|
||||
static inline void* sarray_get_safe(struct sarray* array, sidx index)
|
||||
{
|
||||
if(soffset_decode(index) < array->capacity)
|
||||
return sarray_get(array, index);
|
||||
else
|
||||
return (array->empty_bucket->elems[0]);
|
||||
}
|
||||
|
||||
#endif /* __sarray_INCLUDE_GNU */
|
||||
|
|
@ -1,458 +0,0 @@
|
|||
/* GNU Objective C Runtime selector related functions
|
||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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
|
||||
GNU CC; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
#include "runtime.h"
|
||||
#include "objc/sarray.h"
|
||||
#include "encoding.h"
|
||||
|
||||
/* Initial selector hash table size. Value doesn't matter much */
|
||||
#define SELECTOR_HASH_SIZE 128
|
||||
|
||||
/* Tables mapping selector names to uid and opposite */
|
||||
static struct sarray* __objc_selector_array = 0; /* uid -> sel !T:MUTEX */
|
||||
static struct sarray* __objc_selector_names = 0; /* uid -> name !T:MUTEX */
|
||||
static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
|
||||
|
||||
static void register_selectors_from_list(MethodList_t);
|
||||
|
||||
/* Number of selectors stored in each of the above tables */
|
||||
int __objc_selector_max_index = 0; /* !T:MUTEX */
|
||||
|
||||
void __objc_init_selector_tables()
|
||||
{
|
||||
__objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
|
||||
__objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
|
||||
__objc_selector_hash
|
||||
= hash_new (SELECTOR_HASH_SIZE,
|
||||
(hash_func_type) hash_string,
|
||||
(compare_func_type) compare_strings);
|
||||
}
|
||||
|
||||
/* This routine is given a class and records all of the methods in its class
|
||||
structure in the record table. */
|
||||
void
|
||||
__objc_register_selectors_from_class (Class class)
|
||||
{
|
||||
MethodList_t method_list;
|
||||
|
||||
method_list = class->methods;
|
||||
while (method_list)
|
||||
{
|
||||
register_selectors_from_list (method_list);
|
||||
method_list = method_list->method_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This routine is given a list of methods and records each of the methods in
|
||||
the record table. This is the routine that does the actual recording
|
||||
work.
|
||||
|
||||
This one is only called for Class objects. For categories,
|
||||
class_add_method_list is called.
|
||||
*/
|
||||
static void
|
||||
register_selectors_from_list (MethodList_t method_list)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < method_list->method_count)
|
||||
{
|
||||
Method_t method = &method_list->method_list[i];
|
||||
method->method_name
|
||||
= sel_register_typed_name ((const char*)method->method_name,
|
||||
method->method_types);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Register instance methods as class methods for root classes */
|
||||
void __objc_register_instance_methods_to_class(Class class)
|
||||
{
|
||||
MethodList_t method_list;
|
||||
MethodList_t class_method_list;
|
||||
int max_methods_no = 16;
|
||||
MethodList_t new_list;
|
||||
Method_t curr_method;
|
||||
|
||||
/* Only if a root class. */
|
||||
if(class->super_class)
|
||||
return;
|
||||
|
||||
/* Allocate a method list to hold the new class methods */
|
||||
new_list = objc_calloc(sizeof(struct objc_method_list)
|
||||
+ sizeof(struct objc_method[max_methods_no]), 1);
|
||||
method_list = class->methods;
|
||||
class_method_list = class->class_pointer->methods;
|
||||
curr_method = &new_list->method_list[0];
|
||||
|
||||
/* Iterate through the method lists for the class */
|
||||
while (method_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Iterate through the methods from this method list */
|
||||
for (i = 0; i < method_list->method_count; i++)
|
||||
{
|
||||
Method_t mth = &method_list->method_list[i];
|
||||
if (mth->method_name
|
||||
&& !search_for_method_in_list (class_method_list,
|
||||
mth->method_name))
|
||||
{
|
||||
/* This instance method isn't a class method.
|
||||
Add it into the new_list. */
|
||||
*curr_method = *mth;
|
||||
|
||||
/* Reallocate the method list if necessary */
|
||||
if(++new_list->method_count == max_methods_no)
|
||||
new_list =
|
||||
objc_realloc(new_list, sizeof(struct objc_method_list)
|
||||
+ sizeof(struct
|
||||
objc_method[max_methods_no += 16]));
|
||||
curr_method = &new_list->method_list[new_list->method_count];
|
||||
}
|
||||
}
|
||||
|
||||
method_list = method_list->method_next;
|
||||
}
|
||||
|
||||
/* If we created any new class methods
|
||||
then attach the method list to the class */
|
||||
if (new_list->method_count)
|
||||
{
|
||||
new_list =
|
||||
objc_realloc(new_list, sizeof(struct objc_method_list)
|
||||
+ sizeof(struct objc_method[new_list->method_count]));
|
||||
new_list->method_next = class->class_pointer->methods;
|
||||
class->class_pointer->methods = new_list;
|
||||
}
|
||||
|
||||
__objc_update_dispatch_table_for_class (class->class_pointer);
|
||||
}
|
||||
|
||||
|
||||
/* Returns YES iff t1 and t2 have same method types, but we ignore
|
||||
the argframe layout */
|
||||
BOOL
|
||||
sel_types_match (const char* t1, const char* t2)
|
||||
{
|
||||
if (!t1 || !t2)
|
||||
return NO;
|
||||
while (*t1 && *t2)
|
||||
{
|
||||
if (*t1 == '+') t1++;
|
||||
if (*t2 == '+') t2++;
|
||||
while (isdigit(*t1)) t1++;
|
||||
while (isdigit(*t2)) t2++;
|
||||
/* xxx Remove these next two lines when qualifiers are put in
|
||||
all selectors, not just Protocol selectors. */
|
||||
t1 = objc_skip_type_qualifiers(t1);
|
||||
t2 = objc_skip_type_qualifiers(t2);
|
||||
if (!*t1 && !*t2)
|
||||
return YES;
|
||||
if (*t1 != *t2)
|
||||
return NO;
|
||||
t1++;
|
||||
t2++;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* return selector representing name */
|
||||
SEL
|
||||
sel_get_typed_uid (const char *name, const char *types)
|
||||
{
|
||||
struct objc_list *l;
|
||||
sidx i;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||
if (i == 0)
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
||||
l; l = l->tail)
|
||||
{
|
||||
SEL s = (SEL)l->head;
|
||||
if (types == 0 || s->sel_types == 0)
|
||||
{
|
||||
if (s->sel_types == types)
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
else if (sel_types_match (s->sel_types, types))
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return selector representing name; prefer a selector with non-NULL type */
|
||||
SEL
|
||||
sel_get_any_typed_uid (const char *name)
|
||||
{
|
||||
struct objc_list *l;
|
||||
sidx i;
|
||||
SEL s = NULL;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||
if (i == 0)
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
||||
l; l = l->tail)
|
||||
{
|
||||
s = (SEL) l->head;
|
||||
if (s->sel_types)
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* return selector representing name */
|
||||
SEL
|
||||
sel_get_any_uid (const char *name)
|
||||
{
|
||||
struct objc_list *l;
|
||||
sidx i;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||
if (soffset_decode (i) == 0)
|
||||
{
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
if (l == 0)
|
||||
return 0;
|
||||
|
||||
return (SEL)l->head;
|
||||
}
|
||||
|
||||
/* return selector representing name */
|
||||
SEL
|
||||
sel_get_uid (const char *name)
|
||||
{
|
||||
return sel_register_typed_name (name, 0);
|
||||
}
|
||||
|
||||
/* Get name of selector. If selector is unknown, the empty string ""
|
||||
is returned */
|
||||
const char*
|
||||
sel_get_name (SEL selector)
|
||||
{
|
||||
const char *ret;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
if ((soffset_decode((sidx)selector->sel_id) > 0)
|
||||
&& (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
|
||||
ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
|
||||
else
|
||||
ret = 0;
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
sel_is_mapped (SEL selector)
|
||||
{
|
||||
unsigned int idx = soffset_decode ((sidx)selector->sel_id);
|
||||
return ((idx > 0) && (idx <= __objc_selector_max_index));
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
sel_get_type (SEL selector)
|
||||
{
|
||||
if (selector)
|
||||
return selector->sel_types;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The uninstalled dispatch table */
|
||||
extern struct sarray* __objc_uninstalled_dtable;
|
||||
|
||||
/* Store the passed selector name in the selector record and return its
|
||||
selector value (value returned by sel_get_uid).
|
||||
Assumes that the calling function has locked down __objc_runtime_mutex. */
|
||||
/* is_const parameter tells us if the name and types parameters
|
||||
are really constant or not. If YES then they are constant and
|
||||
we can just store the pointers. If NO then we need to copy
|
||||
name and types because the pointers may disappear later on. */
|
||||
SEL
|
||||
__sel_register_typed_name (const char *name, const char *types,
|
||||
struct objc_selector *orig, BOOL is_const)
|
||||
{
|
||||
struct objc_selector* j;
|
||||
sidx i;
|
||||
struct objc_list *l;
|
||||
|
||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||
if (soffset_decode (i) != 0)
|
||||
{
|
||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
||||
l; l = l->tail)
|
||||
{
|
||||
SEL s = (SEL)l->head;
|
||||
if (types == 0 || s->sel_types == 0)
|
||||
{
|
||||
if (s->sel_types == types)
|
||||
{
|
||||
if (orig)
|
||||
{
|
||||
orig->sel_id = (void*)i;
|
||||
return orig;
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (s->sel_types, types))
|
||||
{
|
||||
if (orig)
|
||||
{
|
||||
orig->sel_id = (void*)i;
|
||||
return orig;
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
}
|
||||
if (orig)
|
||||
j = orig;
|
||||
else
|
||||
j = objc_malloc (sizeof (struct objc_selector));
|
||||
|
||||
j->sel_id = (void*)i;
|
||||
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
||||
if ((is_const) || (types == 0))
|
||||
j->sel_types = (const char*)types;
|
||||
else {
|
||||
j->sel_types = (char *) objc_malloc(strlen(types)+1);
|
||||
strcpy((char *)j->sel_types, types);
|
||||
}
|
||||
l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
__objc_selector_max_index += 1;
|
||||
i = soffset_encode(__objc_selector_max_index);
|
||||
if (orig)
|
||||
j = orig;
|
||||
else
|
||||
j = objc_malloc (sizeof (struct objc_selector));
|
||||
|
||||
j->sel_id = (void*)i;
|
||||
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
||||
if ((is_const) || (types == 0))
|
||||
j->sel_types = (const char*)types;
|
||||
else {
|
||||
j->sel_types = (char *) objc_malloc(strlen(types)+1);
|
||||
strcpy((char *)j->sel_types, types);
|
||||
}
|
||||
l = 0;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
|
||||
soffset_decode (i));
|
||||
|
||||
{
|
||||
int is_new = (l == 0);
|
||||
const char *new_name;
|
||||
|
||||
/* Can we use the pointer or must copy name? Don't copy if NULL */
|
||||
if ((is_const) || (name == 0))
|
||||
new_name = name;
|
||||
else {
|
||||
new_name = (char *) objc_malloc(strlen(name)+1);
|
||||
strcpy((char *)new_name, name);
|
||||
}
|
||||
|
||||
l = list_cons ((void*)j, l);
|
||||
sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
|
||||
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
|
||||
if (is_new)
|
||||
hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
|
||||
}
|
||||
|
||||
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
|
||||
|
||||
return (SEL) j;
|
||||
}
|
||||
|
||||
SEL
|
||||
sel_register_name (const char *name)
|
||||
{
|
||||
SEL ret;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
/* Assume that name is not constant static memory and needs to be
|
||||
copied before put into a runtime structure. is_const == NO */
|
||||
ret = __sel_register_typed_name (name, 0, 0, NO);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SEL
|
||||
sel_register_typed_name (const char *name, const char *type)
|
||||
{
|
||||
SEL ret;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
/* Assume that name and type are not constant static memory and need to
|
||||
be copied before put into a runtime structure. is_const == NO */
|
||||
ret = __sel_register_typed_name (name, type, 0, NO);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/* GNU Objective-C Typed Streams interface.
|
||||
Copyright (C) 1993, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled
|
||||
with GCC to produce an executable, this does not cause the resulting
|
||||
executable to be covered by the GNU General Public License. This
|
||||
exception does not however invalidate any other reasons why the
|
||||
executable file might be covered by the GNU General Public License. */
|
||||
|
||||
#ifndef __typedstream_INCLUDE_GNU
|
||||
#define __typedstream_INCLUDE_GNU
|
||||
|
||||
#include "objc/objc.h"
|
||||
#include "objc/hash.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef int (*objc_typed_read_func)(void*, char*, int);
|
||||
typedef int (*objc_typed_write_func)(void*, const char*, int);
|
||||
typedef int (*objc_typed_flush_func)(void*);
|
||||
typedef int (*objc_typed_eof_func)(void*);
|
||||
|
||||
#define OBJC_READONLY 0x01
|
||||
#define OBJC_WRITEONLY 0x02
|
||||
|
||||
#define OBJC_MANAGED_STREAM 0x01
|
||||
#define OBJC_FILE_STREAM 0x02
|
||||
#define OBJC_MEMORY_STREAM 0x04
|
||||
|
||||
#define OBJC_TYPED_STREAM_VERSION 0x01
|
||||
|
||||
typedef struct objc_typed_stream {
|
||||
void* physical;
|
||||
cache_ptr object_table; /* read/written objects */
|
||||
cache_ptr stream_table; /* other read/written but shared things.. */
|
||||
cache_ptr class_table; /* class version mapping */
|
||||
cache_ptr object_refs; /* forward references */
|
||||
int mode; /* OBJC_READONLY or OBJC_WRITEONLY */
|
||||
int type; /* MANAGED, FILE, MEMORY etc bit string */
|
||||
int version; /* version used when writing */
|
||||
int writing_root_p;
|
||||
objc_typed_read_func read;
|
||||
objc_typed_write_func write;
|
||||
objc_typed_eof_func eof;
|
||||
objc_typed_flush_func flush;
|
||||
} TypedStream;
|
||||
|
||||
/* opcode masks */
|
||||
#define _B_VALUE 0x1fU
|
||||
#define _B_CODE 0xe0U
|
||||
#define _B_SIGN 0x10U
|
||||
#define _B_NUMBER 0x0fU
|
||||
|
||||
/* standard opcodes */
|
||||
#define _B_INVALID 0x00U
|
||||
#define _B_SINT 0x20U
|
||||
#define _B_NINT 0x40U
|
||||
#define _B_SSTR 0x60U
|
||||
#define _B_NSTR 0x80U
|
||||
#define _B_RCOMM 0xa0U
|
||||
#define _B_UCOMM 0xc0U
|
||||
#define _B_EXT 0xe0U
|
||||
|
||||
/* eXtension opcodes */
|
||||
#define _BX_OBJECT 0x00U
|
||||
#define _BX_CLASS 0x01U
|
||||
#define _BX_SEL 0x02U
|
||||
#define _BX_OBJREF 0x03U
|
||||
#define _BX_OBJROOT 0x04U
|
||||
#define _BX_EXT 0x1fU
|
||||
|
||||
/*
|
||||
** Read and write objects as specified by TYPE. All the `last'
|
||||
** arguments are pointers to the objects to read/write.
|
||||
*/
|
||||
|
||||
int objc_write_type (TypedStream* stream, const char* type, const void* data);
|
||||
int objc_read_type (TypedStream* stream, const char* type, void* data);
|
||||
|
||||
int objc_write_types (TypedStream* stream, const char* type, ...);
|
||||
int objc_read_types (TypedStream* stream, const char* type, ...);
|
||||
|
||||
int objc_write_object_reference (TypedStream* stream, id object);
|
||||
int objc_write_root_object (TypedStream* stream, id object);
|
||||
|
||||
long objc_get_stream_class_version (TypedStream* stream, Class class);
|
||||
|
||||
|
||||
/*
|
||||
** Convenience functions
|
||||
*/
|
||||
|
||||
int objc_write_array (TypedStream* stream, const char* type,
|
||||
int count, const void* data);
|
||||
int objc_read_array (TypedStream* stream, const char* type,
|
||||
int count, void* data);
|
||||
|
||||
int objc_write_object (TypedStream* stream, id object);
|
||||
int objc_read_object (TypedStream* stream, id* object);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Open a typed stream for reading or writing. MODE may be either of
|
||||
** OBJC_READONLY or OBJC_WRITEONLY.
|
||||
*/
|
||||
|
||||
TypedStream* objc_open_typed_stream (FILE* physical, int mode);
|
||||
TypedStream* objc_open_typed_stream_for_file (const char* file_name, int mode);
|
||||
|
||||
void objc_close_typed_stream (TypedStream* stream);
|
||||
|
||||
BOOL objc_end_of_typed_stream (TypedStream* stream);
|
||||
void objc_flush_typed_stream (TypedStream* stream);
|
||||
|
||||
#endif /* not __typedstream_INCLUDE_GNU */
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# Use the libio which comes with the local libc.
|
||||
|
||||
# Comment this out to avoid including the stdio functions in libiostream.a:
|
||||
# LIBIOSTREAM_OBJECTS = $(IO_OBJECTS) $(IOSTREAM_OBJECTS) $(STDIO_WRAP_OBJECTS) $(OSPRIM_OBJECTS)
|
||||
# LIBIOSTREAM_DEP = $(LIBIOSTREAM_OBJECTS) stdio.list
|
||||
# LIBIOSTREAM_USE = $(LIBIOSTREAM_OBJECTS) `cat stdio.list`
|
||||
|
||||
# Comment the above and uncomment the below to use the code in the Linux libc:
|
||||
# We have _G_config.h in /usr/include.
|
||||
_G_CONFIG_H=
|
||||
|
||||
# We must not see the libio.h file from this library.
|
||||
LIBIO_INCLUDE=
|
||||
|
||||
# We have those in libc.a.
|
||||
IO_OBJECTS= iogetline.o
|
||||
STDIO_WRAP_OBJECTS=
|
||||
OSPRIM_OBJECTS=
|
||||
STDIO_OBJECTS=
|
||||
|
||||
# We have the rest in /usr/include.
|
||||
USER_INCLUDES=PlotFile.h SFile.h builtinbuf.h editbuf.h fstream.h \
|
||||
indstream.h iomanip.h iostream.h istream.h ostream.h \
|
||||
parsestream.h pfstream.h procbuf.h stdiostream.h stream.h \
|
||||
streambuf.h strfile.h strstream.h
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# Use the libio which comes with the local libc.
|
||||
|
||||
# Comment this out to avoid including the stdio functions in libiostream.a:
|
||||
# LIBIOSTREAM_OBJECTS = $(IO_OBJECTS) $(IOSTREAM_OBJECTS) $(STDIO_WRAP_OBJECTS) $(OSPRIM_OBJECTS)
|
||||
# LIBIOSTREAM_DEP = $(LIBIOSTREAM_OBJECTS) stdio.list
|
||||
# LIBIOSTREAM_USE = $(LIBIOSTREAM_OBJECTS) `cat stdio.list`
|
||||
|
||||
# Comment the above and uncomment the below to use the code in the Linux libc:
|
||||
# We have _G_config.h in /usr/include.
|
||||
_G_CONFIG_H=
|
||||
|
||||
# We must not see the libio.h file from this library.
|
||||
LIBIO_INCLUDE=
|
||||
|
||||
# We have those in libc.a.
|
||||
IO_OBJECTS= iogetline.o
|
||||
STDIO_WRAP_OBJECTS=
|
||||
OSPRIM_OBJECTS=
|
||||
STDIO_OBJECTS=
|
||||
|
||||
# We have the rest in /usr/include.
|
||||
USER_INCLUDES=PlotFile.h SFile.h builtinbuf.h editbuf.h fstream.h \
|
||||
indstream.h iomanip.h iostream.h istream.h ostream.h \
|
||||
parsestream.h pfstream.h procbuf.h stdiostream.h stream.h \
|
||||
streambuf.h strfile.h strstream.h
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# Flags to pass to gen-params when building _G_config.h.
|
||||
# For example: G_CONFIG_ARGS = size_t="unsigned long"
|
||||
G_CONFIG_ARGS = DOLLAR_IN_LABEL=1
|
||||
|
||||
#
|
||||
# gen-params tries to determine whether or not printf_fp exists by
|
||||
# simply compiling a test program. Since MPE is by definition a
|
||||
# shared runtime environment, this won't work unless the resulting
|
||||
# program is run. Simply run _G_config.h through a sed script to
|
||||
# update the values accordingly.
|
||||
#
|
||||
_G_CONFIG_H = stmp-Gconfig
|
||||
|
||||
stmp-Gconfig: _G_config.h
|
||||
sed -e "s/_G_HAVE_PRINTF_FP 1/_G_HAVE_PRINTF_FP 0/" \
|
||||
-e "s/_G_HAVE_LONG_DOUBLE_IO 1/_G_HAVE_LONG_DOUBLE_IO 0/" \
|
||||
<_G_config.h > tmp-config.h
|
||||
mv -f tmp-config.h _G_config.h
|
||||
touch stmp-Gconfig
|
||||
$(MAKE) $(FLAGS_TO_PASS) _G_CONFIG_H=_G_config.h all
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Flags to pass to gen-params when building _G_config.h.
|
||||
# For example: G_CONFIG_ARGS = size_t="unsigned long"
|
||||
G_CONFIG_ARGS = MATH_H_INLINES=1
|
||||
|
|
@ -1 +0,0 @@
|
|||
G_CONFIG_ARGS = HAVE_PRINTF_FP=0 HAVE_LONG_DOUBLE_IO=0
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
LIBS = $(ARLIB) $(ARLINK) $(SHLIB) mshlink $(SHLINK)
|
||||
SHFLAGS = -Wl,-soname,$(MSHLINK)
|
||||
DEPLIBS = ../$(SHLIB)
|
||||
SHOPT = -nostart
|
||||
Loading…
Reference in a new issue