> According to the C language operator precedence rules, the
> application of the '&' operator should come after the application
> of all the other operators used in "&pass[i].lm_pwd". The array
> reference comes first, then the member or union reference "dot".
> Then the address of that location is what is passed to memset. The
> memset is supposed to zero the lm_pwd part of the structure which
> is the i-th element in the "pass" array.
Yes.
> If the "&" (which reads as 'address of') is ignored, then memset
> will get the -value- of lm_pwd, which is then interpreted as an
> address, and *that* is zeroed. Since the value of lm_pwd is not a
> pointer (lm_pwd is an array of uint8), the memset will probably
> corrupt memory, or cause a segfault.
No.
C passes arrays 'by reference', i.e. not the contents of the array is
pushed on the stack but its address.
If 'pass[i].lm_pwd' is an argument of a function, the
*address* of the lm_pwd part of the i-th element of pass is
pushed on the stack.
In contrast, pointers are regarded as integers and passed 'by value',
i.e. their value is pushed on the stack.
If '&pass[i].lm_pwd' is an argument of a function, the
address of the lm_pwd part of the i-th element of pass is
computed and this *value* is pushed on the stack.
That is, with regard to the stack, "&pass[i].lm_pwd" and
"pass[i].lm_pwd" are just synonymous.
However, the ampersand version passes the address of an array of
UINT8 by value, and the non-ampersand version passes an array of
UINT8 by reference, so a compiler doing over-pedantic type checking
may give a warning, even if a void* is expected.
Just decrease the warning level.
Ludolf
---------------------------------------------------------------
Ludolf Holzheid Tel: +49 621 3392723
Bihl+Wiedemann GmbH Fax: +49 621 3392239
Flosswoerthstrasse 41 e-mail LHol...@Bihl-Wiedemann.de
D-68199 Mannheim, Germany
---------------------------------------------------------------
------_=_NextPart_001_01C1609D.1CE4BA40
Content-Type: text/plain;
charset="iso-8859-1"
According to the C language operator precedence rules, the application of
the '&' operator should come after the application of all the other
operators used in "&pass[i].lm_pwd". The array reference comes first, then
the member or union reference "dot". Then the address of that location is
what is passed to memset. The memset is supposed to zero the lm_pwd part of
the structure which is the i-th element in the "pass" array. If the "&"
(which reads as 'address of') is ignored, then memset will get the -value-
of lm_pwd, which is then interpreted as an address, and *that* is zeroed.
Since the value of lm_pwd is not a pointer (lm_pwd is an array of uint8),
the memset will probably corrupt memory, or cause a segfault.
I think the main thing to focus on is the fact that you were able to compile
the same code with the gnu compiler, and you did not have the same problems.
I am unfamiliar with the DU compiler, so I shouldn't try to guess why it's
acting this way. Perhaps the warning level is set so high that it's trying
to do extremely strict type checking. The warnings seem to focus on the
difference between an array, and a pointer. In most C circles, the two are
interchangeable, so long as the pointer is defined as one that points at the
same type of thing as an element in the array. This comes from a string
pointer (char *) reference being the same as the address of the first
element in an array of chars (&str[0]). Maybe the DU compiler is trying to
warn you that an open ended pointer is not the same as a closed end array,
unless more strict definitions are used.
Try this: Declare a pointer "p" of type "uint8 *", and assign it the value
of "&pass[i].lm_pwd" at that point in the code. Then pass "p" to memset.
uint8 *p = &pass[i].lm_pwd;
memset(p, '\0', 16 * sizeof(uint8));
Of course this code is wrong from a maintainability standpoint, since we are
hard coding the size of the uint8 array, but it's just a test.
See if the compiler complains about that. If not, then the problem is
probably type check warnings set too high.
This is not a problem of Kernighan & Ritchie vs ANSI C. They both use the
'&' operator. We'd be lost without it.
-----Original Message-----
From: Boyce, Nick [mailto:nick....@eds.com]
Sent: Monday, October 29, 2001 10:31 AM
To: 'samba-t...@lists.samba.org'
Cc: 'Esh, Andrew'
Subject: RE: 2.2.2 Compilation Warnings On Tru64 / Digital Unix
Andrew Esh wrote :
> Nick Boyce wrote :
>
>> [My apologies for bothering this list if this is not appropriate]
>> I have just tried building Samba 2.2.2 *--with-winbind* on both Digital
Unix
>> 4.0D (= Tru64) and NetBSD 1.4.1, and got a *lot* of compilation warnings
>
> No apology necessary. This message is certainly appropriate for this list,
above all other lists.
Phew :-)
> I couldn't pay me to take that Digital compiler off your hands. It ignores
> the ampersand in front of "pass[i].lm_pwd"? That's not just being
> incompatible with the differences between certain flavors of C, it's being
> incompatible with the C *language*. Something is seriously wrong with
> that compiler.
Well you've worried me more now than I probably horrified *you* !
I'm not much of a C programmer, so the immediate implications of the
compiler diagnostics were lost on me, but your message persuaded me to think
further.
My understanding is that the '&' is there to indicate address indirection -
("pointers" in C-speak ?). In which case, as an example, I deduce that the
compiler diagnostic :
cc: Warning: rpc_server/srv_samr_nt.c, line 683: In this statement, &
before array "pass[i].lm_pwd" is ignored.
memset(&pass[i].lm_pwd, '\0', sizeof(pass[i].lm_pwd));
means that instead of zeroising the memory location whose address is in
'pass[i].lmpwd', my C compiler is generating code to zeroise 'pass[i].lmpwd'
itself. If that's right, then it's horrific ... so horrific that I can't
quite believe Compaq/DEC's "new" C compiler for DU 4.0D (a widely used
Y2K-fixed OS release), with Digital Unix Patch Kits 1 thru 5 installed,
could possibly have such an appalling compiler bug ...
Is it possible that the compiler is saying it can ignore the '&' because
it's obvious from the context that '&' is intended/required ?
Or is it possible that this is a K&R C versus ANSI C thing ?
Or an "array of pointers" versus "pointer to array" ambiguity ?
I had a look at the DU "cc" manpage - it contains this :-
========================================================
-std[n]
Directs the compiler to produce warnings for language constructs that
are not standard in the language. The default is -std0.
The following values are accepted:
-std
Enforces the ANSI C standard, but allows some common programming
practices disallowed by the standard. The -std flag causes the
macro __STDC__=0 to be passed to the preprocessor.
-std0
Enforces the K&R programming style, with certain ANSI extensions
in
areas where the K & R behavior is undefined or ambiguous. In gen-
eral, -std0 compiles most pre-ANSI C programs and produces
expected
results. The -std0 flag causes the __STDC__ macro to be undefined.
-std1
Strictly enforces the ANSI C standard and all its prohibitions
(such as those that apply to the handling of void types, the
defin-
ition of lvalues in expressions, the mixing of integrals and
pointers, and the modification of rvalues). This flag does not,
however, restrict the name space defined by the DIGITAL UNIX
imple-
mentation to only reserved names as specified by ANSI C.
The -std1 flag causes the macro __STDC__=1 to be passed to the
preprocessor. Note that the -std1 flag also affects linker
defined
symbols. See ld(1) for more information.
========================================================
Do you think any of these flags might help ?
> This is really curious, considering your statement about being able
> to compile Samba 2.0.7 with the same compiler. The combination
> of all these statements yields an absurdity. You need to double check.
Well I just reran a build for Samba 2.0.7 on our DU box, and
(a) there are definitely no warnings
(b) the build log is only 6966 bytes long, compared with the 17313 byte
build log for 2.2.2 - i.e. there is clearly a lot more stuff in 2.2.2 - and
some of that doesn't build nicely on DU 4.0D.
What about some of the other warnings I got :-
cc: Warning: rpc_server/srv_spoolss_nt.c, line 3658: In this statement,
the referenced type of the pointer value "&nullstr" is "signed char", which
is not compatible with "array [256] of signed char".
init_unistr_array(&info->previousdrivernames, &nullstr,
servername);
--------^
cc: Warning: lib/util.c, line 559: In this statement, the referenced type
of the pointer value "read" is "function () returning int", which is not
compatible with "function (int, pointer to void, unsigned long) returning
long".
return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n,
read, write);
--------------------------^
cc: Warning: tdb/tdb.c, line 106: In this statement, "(-1)" of type
"long", is being converted to "pointer to void".
if (tdb->map_ptr == MAP_FAILED) {
--------------------^
Do you think they're as spurious as the ignoring '&' thing ?
> Maybe you can get gcc working on Digital, and use that instead of cc
I'll have a look at that - last time I tried installing gcc (2.7.1.? on
Ultrix) it was a very laborious, time-consuming and nervewracking procedure,
so I'm reluctant ... but I know I should ...
It's not as if Compaq are sheepish or embarassed about their C compilers -
they're proud - see http://www.tru64unix.compaq.com/dtk/
> Are you sure someone didn't symlink /usr/bin/cc to /usr/games/fortune?
The b*stards - I'll lock their accounts out just as soon as I find out who
...
:-)
Nick Boyce
EDS Southwest Solution Centre, Bristol, UK
------_=_NextPart_001_01C1609D.1CE4BA40
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Diso-8859-1">
<META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
5.5.2650.12">
<TITLE>RE: 2.2.2 Compilation Warnings On Tru64 / Digital Unix</TITLE>
</HEAD>
<BODY>
<P><FONT SIZE=3D2>According to the C language operator precedence =
rules, the application of the '&' operator should come after the =
application of all the other operators used in =
"&pass[i].lm_pwd". The array reference comes first, then =
the member or union reference "dot". Then the address of that =
location is what is passed to memset. The memset is supposed to zero =
the lm_pwd part of the structure which is the i-th element in the =
"pass" array. If the "&" (which reads as =
'address of') is ignored, then memset will get the -value- of lm_pwd, =
which is then interpreted as an address, and *that* is zeroed. Since =
the value of lm_pwd is not a pointer (lm_pwd is an array of uint8), the =
memset will probably corrupt memory, or cause a segfault.</FONT></P>
<P><FONT SIZE=3D2>I think the main thing to focus on is the fact that =
you were able to compile the same code with the gnu compiler, and you =
did not have the same problems. I am unfamiliar with the DU compiler, =
so I shouldn't try to guess why it's acting this way. Perhaps the =
warning level is set so high that it's trying to do extremely strict =
type checking. The warnings seem to focus on the difference between an =
array, and a pointer. In most C circles, the two are interchangeable, =
so long as the pointer is defined as one that points at the same type =
of thing as an element in the array. This comes from a string pointer =
(char *) reference being the same as the address of the first element =
in an array of chars (&str[0]). Maybe the DU compiler is trying to =
warn you that an open ended pointer is not the same as a closed end =
array, unless more strict definitions are used.</FONT></P>
<P><FONT SIZE=3D2>Try this: Declare a pointer "p" of type =
"uint8 *", and assign it the value of =
"&pass[i].lm_pwd" at that point in the code. Then pass =
"p" to memset.</FONT></P>
<P> <FONT SIZE=3D2>uint8 *p =
=3D &pass[i].lm_pwd;</FONT>
<BR> <FONT SIZE=3D2>memset(p, =
'\0', 16 * sizeof(uint8));</FONT>
</P>
<P><FONT SIZE=3D2>Of course this code is wrong from a maintainability =
standpoint, since we are hard coding the size of the uint8 array, but =
it's just a test.</FONT></P>
<P><FONT SIZE=3D2>See if the compiler complains about that. If not, =
then the problem is probably type check warnings set too high.</FONT>
</P>
<P><FONT SIZE=3D2>This is not a problem of Kernighan & Ritchie vs =
ANSI C. They both use the '&' operator. We'd be lost without =
it.</FONT>
</P>
<P><FONT SIZE=3D2>-----Original Message-----</FONT>
<BR><FONT SIZE=3D2>From: Boyce, Nick [<A =
HREF=3D"mailto:nick....@eds.com">mailto:nick....@eds.com</A>]</FONT>=
<BR><FONT SIZE=3D2>Sent: Monday, October 29, 2001 10:31 AM</FONT>
<BR><FONT SIZE=3D2>To: 'samba-t...@lists.samba.org'</FONT>
<BR><FONT SIZE=3D2>Cc: 'Esh, Andrew'</FONT>
<BR><FONT SIZE=3D2>Subject: RE: 2.2.2 Compilation Warnings On Tru64 / =
Digital Unix</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>Andrew Esh wrote :</FONT>
</P>
<P><FONT SIZE=3D2>> Nick Boyce wrote :</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>>> [My apologies for bothering this list if =
this is not appropriate] </FONT>
<BR><FONT SIZE=3D2>>> I have just tried building Samba 2.2.2 =
*--with-winbind* on both Digital</FONT>
<BR><FONT SIZE=3D2>Unix </FONT>
<BR><FONT SIZE=3D2>>> 4.0D (=3D Tru64) and NetBSD 1.4.1, and got =
a *lot* of compilation warnings</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> No apology necessary. This message is certainly =
appropriate for this list,</FONT>
<BR><FONT SIZE=3D2>above all other lists. </FONT>
</P>
<P><FONT SIZE=3D2>Phew :-) </FONT>
</P>
<P><FONT SIZE=3D2>> I couldn't pay me to take that Digital compiler =
off your hands. It ignores</FONT>
</P>
<P><FONT SIZE=3D2>> the ampersand in front of =
"pass[i].lm_pwd"? That's not just being </FONT>
<BR><FONT SIZE=3D2>> incompatible with the differences between =
certain flavors of C, it's being</FONT>
</P>
<P><FONT SIZE=3D2>> incompatible with the C *language*. Something is =
seriously wrong with </FONT>
<BR><FONT SIZE=3D2>> that compiler. </FONT>
</P>
<P><FONT SIZE=3D2>Well you've worried me more now than I probably =
horrified *you* !</FONT>
</P>
<P><FONT SIZE=3D2>I'm not much of a C programmer, so the immediate =
implications of the</FONT>
<BR><FONT SIZE=3D2>compiler diagnostics were lost on me, but your =
message persuaded me to think</FONT>
<BR><FONT SIZE=3D2>further.</FONT>
</P>
<P><FONT SIZE=3D2>My understanding is that the '&' is there to =
indicate address indirection -</FONT>
<BR><FONT SIZE=3D2>("pointers" in C-speak ?). In which =
case, as an example, I deduce that the</FONT>
<BR><FONT SIZE=3D2>compiler diagnostic :</FONT>
<BR><FONT SIZE=3D2> cc: Warning: =
rpc_server/srv_samr_nt.c, line 683: In this statement, &</FONT>
<BR><FONT SIZE=3D2>before array "pass[i].lm_pwd" is ignored. =
</FONT>
<BR><FONT =
SIZE=3D2> &nb=
sp; =
memset(&pass[i].lm_pwd, '\0', sizeof(pass[i].lm_pwd)); </FONT>
<BR><FONT SIZE=3D2>means that instead of zeroising the memory location =
whose address is in</FONT>
<BR><FONT SIZE=3D2>'pass[i].lmpwd', my C compiler is generating code to =
zeroise 'pass[i].lmpwd'</FONT>
<BR><FONT SIZE=3D2>itself. If that's right, then it's horrific =
... so horrific that I can't</FONT>
<BR><FONT SIZE=3D2>quite believe Compaq/DEC's "new" C =
compiler for DU 4.0D (a widely used</FONT>
<BR><FONT SIZE=3D2>Y2K-fixed OS release), with Digital Unix Patch Kits =
1 thru 5 installed,</FONT>
<BR><FONT SIZE=3D2>could possibly have such an appalling compiler bug =
...</FONT>
</P>
<P><FONT SIZE=3D2>Is it possible that the compiler is saying it can =
ignore the '&' because</FONT>
<BR><FONT SIZE=3D2>it's obvious from the context that '&' is =
intended/required ?</FONT>
</P>
<P><FONT SIZE=3D2>Or is it possible that this is a K&R C versus =
ANSI C thing ?</FONT>
</P>
<P><FONT SIZE=3D2>Or an "array of pointers" versus =
"pointer to array" ambiguity ?</FONT>
</P>
<P><FONT SIZE=3D2>I had a look at the DU "cc" manpage - it =
contains this :-</FONT>
</P>
<P><FONT =
SIZE=3D2>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D</FONT>
<BR><FONT SIZE=3D2> -std[n]</FONT>
<BR><FONT SIZE=3D2> Directs the compiler =
to produce warnings for language constructs that</FONT>
<BR><FONT SIZE=3D2> are not standard in =
the language. The default is -std0.</FONT>
</P>
<P><FONT SIZE=3D2> The following values =
are accepted:</FONT>
</P>
<P><FONT SIZE=3D2> -std</FONT>
<BR><FONT =
SIZE=3D2> =
Enforces the ANSI C standard, but allows some common programming</FONT>
<BR><FONT =
SIZE=3D2> =
practices disallowed by the standard. The -std flag causes the</FONT>
<BR><FONT =
SIZE=3D2> macro =
__STDC__=3D0 to be passed to the preprocessor.</FONT>
</P>
<P><FONT SIZE=3D2> -std0</FONT>
<BR><FONT =
SIZE=3D2> =
Enforces the K&R programming style, with certain ANSI =
extensions</FONT>
<BR><FONT SIZE=3D2>in</FONT>
<BR><FONT SIZE=3D2>  =
; areas where the K & R behavior is undefined or ambiguous. =
In gen-</FONT>
<BR><FONT =
SIZE=3D2> eral, =
-std0 compiles most pre-ANSI C programs and produces</FONT>
<BR><FONT SIZE=3D2>expected</FONT>
<BR><FONT =
SIZE=3D2> =
results. The -std0 flag causes the __STDC__ macro to be =
undefined.</FONT>
</P>
<P><FONT SIZE=3D2> -std1</FONT>
<BR><FONT =
SIZE=3D2> =
Strictly enforces the ANSI C standard and all its prohibitions</FONT>
<BR><FONT =
SIZE=3D2> (such =
as those that apply to the handling of void types, the</FONT>
<BR><FONT SIZE=3D2>defin-</FONT>
<BR><FONT =
SIZE=3D2> ition =
of lvalues in expressions, the mixing of integrals and</FONT>
<BR><FONT =
SIZE=3D2> =
pointers, and the modification of rvalues). This flag does =
not,</FONT>
<BR><FONT =
SIZE=3D2> =
however, restrict the name space defined by the DIGITAL UNIX</FONT>
<BR><FONT SIZE=3D2>imple-</FONT>
<BR><FONT =
SIZE=3D2> =
mentation to only reserved names as specified by ANSI C.</FONT>
</P>
<P><FONT =
SIZE=3D2> The =
-std1 flag causes the macro __STDC__=3D1 to be passed to the</FONT>
<BR><FONT =
SIZE=3D2> =
preprocessor. Note that the -std1 flag also affects linker</FONT>
<BR><FONT SIZE=3D2>defined</FONT>
<BR><FONT =
SIZE=3D2> =
symbols. See ld(1) for more information.</FONT>
<BR><FONT =
SIZE=3D2>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D</FONT>
</P>
<P><FONT SIZE=3D2>Do you think any of these flags might help ?</FONT>
</P>
<P><FONT SIZE=3D2>> This is really curious, considering your =
statement about being able </FONT>
<BR><FONT SIZE=3D2>> to compile Samba 2.0.7 with the same compiler. =
The combination </FONT>
<BR><FONT SIZE=3D2>> of all these statements yields an absurdity. =
You need to double check. </FONT>
</P>
<P><FONT SIZE=3D2>Well I just reran a build for Samba 2.0.7 on our DU =
box, and </FONT>
<BR><FONT SIZE=3D2>(a) there are definitely no warnings</FONT>
<BR><FONT SIZE=3D2>(b) the build log is only 6966 bytes long, compared =
with the 17313 byte</FONT>
<BR><FONT SIZE=3D2>build log for 2.2.2 - i.e. there is clearly a lot =
more stuff in 2.2.2 - and</FONT>
<BR><FONT SIZE=3D2>some of that doesn't build nicely on DU 4.0D.</FONT>
</P>
<P><FONT SIZE=3D2>What about some of the other warnings I got :-</FONT>
</P>
<P><FONT SIZE=3D2> cc: Warning: rpc_server/srv_spoolss_nt.c, line =
3658: In this statement, </FONT>
<BR><FONT SIZE=3D2>the referenced type of the pointer value =
"&nullstr" is "signed char", which </FONT>
<BR><FONT SIZE=3D2>is not compatible with "array [256] of signed =
char". </FONT>
<BR><FONT =
SIZE=3D2> =
init_unistr_array(&info->previousdrivernames, &nullstr, =
</FONT>
<BR><FONT SIZE=3D2>servername); </FONT>
<BR><FONT SIZE=3D2> --------^ </FONT>
</P>
<P><FONT SIZE=3D2> cc: Warning: lib/util.c, line 559: In this =
statement, the referenced type </FONT>
<BR><FONT SIZE=3D2>of the pointer value "read" is =
"function () returning int", which is not </FONT>
<BR><FONT SIZE=3D2>compatible with "function (int, pointer to =
void, unsigned long) returning </FONT>
<BR><FONT SIZE=3D2>long". </FONT>
<BR><FONT =
SIZE=3D2> return =
(SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, </FONT>
<BR><FONT SIZE=3D2>read, write); </FONT>
<BR><FONT SIZE=3D2> --------------------------^ </FONT>
</P>
<P><FONT SIZE=3D2> cc: Warning: tdb/tdb.c, line 106: In this =
statement, "(-1)" of type </FONT>
<BR><FONT SIZE=3D2>"long", is being converted to =
"pointer to void". </FONT>
<BR><FONT =
SIZE=3D2> &nb=
sp; if (tdb->map_ptr =3D=3D =
MAP_FAILED) { </FONT>
<BR><FONT SIZE=3D2> --------------------^ </FONT>
</P>
<P><FONT SIZE=3D2>Do you think they're as spurious as the ignoring =
'&' thing ?</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>> Maybe you can get gcc working on Digital, and =
use that instead of cc</FONT>
</P>
<P><FONT SIZE=3D2>I'll have a look at that - last time I tried =
installing gcc (2.7.1.? on</FONT>
<BR><FONT SIZE=3D2>Ultrix) it was a very laborious, time-consuming and =
nervewracking procedure,</FONT>
<BR><FONT SIZE=3D2>so I'm reluctant ... but I know I should ...</FONT>
</P>
<P><FONT SIZE=3D2>It's not as if Compaq are sheepish or embarassed =
about their C compilers -</FONT>
<BR><FONT SIZE=3D2>they're proud - see <A =
HREF=3D"http://www.tru64unix.compaq.com/dtk/" =
TARGET=3D"_blank">http://www.tru64unix.compaq.com/dtk/</A></FONT>
</P>
<P><FONT SIZE=3D2>> Are you sure someone didn't symlink /usr/bin/cc =
to /usr/games/fortune?</FONT>
</P>
<P><FONT SIZE=3D2>The b*stards - I'll lock their accounts out just as =
soon as I find out who</FONT>
<BR><FONT SIZE=3D2>...</FONT>
</P>
<P><FONT SIZE=3D2>:-)</FONT>
</P>
<P><FONT SIZE=3D2>Nick Boyce</FONT>
<BR><FONT SIZE=3D2>EDS Southwest Solution Centre, Bristol, UK </FONT>
</P>
</BODY>
</HTML>
------_=_NextPart_001_01C1609D.1CE4BA40--