HDTenEightyP/NetNews huggingface dataset:
From: zien@arapaho.ucsc.edu (Jason Yeoung Zien)
Newsgroups: comp.lang.c++
Subject: Priblem with g++ & templates
Keywords: templates g++
Date: 30 Jul 92 05:21:59 GMT
Organization: UC Santa Cruz CIS/CE
NNTP-Posting-Host: arapaho.ucsc.edu

I have been having problems with templates and g++.  I have a program
which compiles fine using ATT CC, but not with g++.  Does anyone
have any hints on how I might get this to work?


Also, is there an easy way of getting separate compilation with templates
to work?  Notice that in my "tem.h" file, I have just used
a #include "tem.C".  


tem.h
--------------
// template<class T> class mytemp;

#ifndef _my_temp_class_
#define _my_temp_class_

template<class T> 
class mytemp {
 private:
  T value;

 public:
  mytemp(T v) {
    value=v;
  }

  T Get() { return(value); }

  void Add(mytemp < T > & other);

  void Print();

};


#include "tem.C"

#endif _my_temp_class_

###############################

tem.C
--------


#include "tem.C"

#endif _my_temp_class_
lancelot 26> cat tem.C

template<class T> void mytemp<T>::Print() {
  cout << "val=" << value << "\n";
}


template < class T >  void mytemp<T>::Add(mytemp < T > & other) {
  value += other.Get();
}

#################################

test.C
--------

#include "tem.h"
#include <stream.h>

main() {
 mytemp<int> ival(3);
 mytemp<double> val(999.999), val2(88.33);

 ival.Print();
 val.Print();
 val.Add(val2);
 val.Print();

}

#######################################


Results
----------
arapaho 21> CC test.C
CC  test.C:
cc  -L/usr/local/C++3.0/lib   test.c -lC

#  (above) CC worked fine....

arapaho 22> g++ test.C
In file included from tem.h:28, from test.C:2:
tem.C:7: parse error before `>'
tem.h:21: parse error before `>'
tem.h:21: parse error before `>'
tem.C: In method `void  mytemp<double>::Add (...)':
tem.C:8: `other' undeclared (first use this function)
tem.C:8: (Each undeclared identifier is reported only once
tem.C:8: for each function it appears in.)
tem.C: In method `void  mytemp<int>::Add (...)':
tem.C:8: `other' undeclared (first use this function)
Xref: sparky comp.lang.c++:11689 comp.std.c++:979
From: chased@rbbb.Eng.Sun.COM (David Chase)
Newsgroups: comp.lang.c++,comp.std.c++
Subject: Re: Language extensions for run-time type identification
Date: 28 Jul 1992 17:57:47 GMT
Organization: Sun Microsystems, Mt. View, Ca.
NNTP-Posting-Host: rbbb
Summary: Definition != Implementation (and vice-versa, one hopes)

In article <1992Jul27.180115.1889@pony.Ingres.COM> bobm@Ingres.COM (Bob McQueer) writes:
>... when I want to know at run time if
>an object is of a particular class, what I really want to ask is "is it this
>class, or any class derived from it?", which implies somebody taking the
>vtable (enhanced into class descriptor) pointer in the object instantiation,
>and ascending through its parents.  With multiple inheritance, there can be
>several flavors of this question.

Do be careful not to confuse the desired meaning of "X is a Foo" with
how it is actually implemented.  For single inheritance, the best
implementation is probably not what you think it is.  For multiple
inheritance, I'm not sure what the best answer is, but I can certainly
imagine a sparse representation of the (bit) matrix encoding the
relation "T1 is a T2".

David Chase
Sun
Newsgroups: comp.lang.c++
From: steve@taumet.com (Steve Clamage)
Subject: Re: reference to C++ assertion macro package?
Keywords: C++, assertions, precondition, postcondition, invariants
Organization: TauMetric Corporation
Date: Sat, 25 Jul 1992 15:26:11 GMT

maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>	Does anyone have details of the proposed assertion
>facility for C++?

The <assert.h> facility from Standard C is part of C++.  I have not seen
any proposals for anything else.  If in particular you mean something
like the pre- and post-conditions for Eiffel classes, I haven't seen any
discussion of them.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16
From: gs4t@virginia.edu (Gnanasekaran Swaminathan)
Newsgroups: comp.lang.c++
Subject: Re: classes referenced each in their declaration
Date: 23 Jul 92 00:37:24 GMT
Reply-To: gs4t@virginia.edu (Gnanasekaran Swaminathan)
Organization: University of Virginia

kinne@delfin.com (Kinne Strong) writes:
> It compiled. Did you try to make an X or a Y? I did. It used up all
> available swap space and died. That's still an infinite object.
> 
> If you say
> 
> 	Y big;
> 
> the space for the first Y is allocated on the stack. It needs an X, so
> it does a new X, which allocates space for the second Y, which also
> needs an X, so it does a new X, which allocates space for the third Y,
> which also needs an X, so ...

Thanks for catching the bug. The following is tested
in GNU C++ and it works.

class Y;

class X {
	Y&	y;
    public:
	X(const Y& y1): y(y1) {}
};

class Y {
	X	x;
    public:
	Y(): x(*this) {}
	Y(const Y& y): x(y) {}
};

main ()
{
	Y y1;
	Y y2 = y1;
	X x1(y1);
	X x2(y2);
}
Newsgroups: comp.lang.c++
From: Jamie Billing-Ross <bross@src.honeywell.com>
Subject: Passing C++ member functions to C functions
Organization: Honeywell Satellite Systems Operation
X-Useragent: Nuntius v1.1b1
Date: Fri, 24 Jul 1992 00:50:47 GMT

This is similar to a problem I have seen stated but I haven't seen an
answer to quite this one.

I have a C routine defined as follows:

extern "C" void add_ext_int_func(int level, int (*ptrfunc)());

Normally I just pass a C interrupt handler function as the 2nd argument

add_ext_int_funct(2,timer_int);

What I would like to do is pass a member function to this same routine..

add_ext_int_funct(2,CCclock::timer_int);

where the call is made from inside another member function of CCclock.
if I typecast the member function,ie (int(*)())CCclock::timer_int I seem
to get only the function offset address rather than the absolute entry
point address..

So I am looking for any suggestions for converting from int(Class::*)() to
a int(*)()

Thanks

Jamie
Newsgroups: comp.lang.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: strdup() Was: Re: Renew?
Organization: Computer Science, University of Melbourne, Australia
Date: Thu, 30 Jul 1992 09:46:20 GMT

hansen@pegasus.att.com (Tony L. Hansen) writes:

>By the way, at least one person has posted a poor version of strdup() which
>didn't check the return value of new. Here's my contribution. As you can
>see, it is a very straightforward function:
>
>    #include <string.h>
>    char *nstrdup(const char *s)
>    {
>	if (!s) s = "";
	^^^^^^^^^^^^^^^
>	char *ret = new char[strlen(s) + 1];
>	if (ret) strcpy(ret, s);
>	return ret;
>    }

If you ask me, the check for ``if (!s) s = "";'' is a really bad idea.
If the program passes you a NULL pointer, then you do NOT want to silently
correct it, you want to let the programmer know that an error has occured.
If you want to program defensively and your machine does not give segmentation
faults when you reference *NULL, then just use assert(s).

The check slows down every call to strdup unnecessarily. (Admittedly not much,
but it is incremental degradation like this that leads to slow bloated
programs.) If you really do want the semantics of your nstrdup(s), just use
	nstrdup(s ? s : "");

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature VIRUS is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.lang.c++,comp.std.c++
From: clark%asylum.cs.utah.edu@cs.utah.edu (Charles Clark)
Subject: Re: Language extensions for run-time type identification
Date: 21 Jul 92 13:55:37 MDT
Followup-To: comp.lang.c++,comp.std.c++
Organization: University of Utah CS Dept

In article <1992Jul21.143131.6902@cadsun.corp.mot.com> shang@corp.mot.com writes:
>In article <14ft2uINNjh4@agate.berkeley.edu> jbuck@forney.berkeley.edu (Joe  
>Buck) writes:
>> * the fact that it is trivial to force any class for which run-time type
>>   identification is needed to have a virtual function table (simply add
>>   a virtual destructor).
>>
>Adding something virtual just for the purpose that has nothing to do with it?

I agree, forcing the programmer to add a virtual destructor (or any virtual 
function) to the design of his/her classes (so the resulting vtable can
be used for type id) is dubious.  Unfortunately, a programmer without access
to a a C++ compiler which provides run-time type id can do no better.

>> In most implementations of classes with virtual functions, each object
>> already has, in effect, a type-ID: the pointer to the virtual function
>> table.  This is a natural hook on which to hang run time type checking.
>>
>The pointer to vtable can not work as a type-ID for a language with multiple  
>inheritance. An object of particular class derived from multiple bases may  
>contain serveral different vtable references. Different base pointers to the  
>same object may use different vtable pointers.

Indeed.  The above scheme fails when vtables are shared between base and 
derived classes.  This sharing occurs when using multiple inheritance 
(or virtual base classes) and no inherited methods from one of the base 
classes are redefined.  A cast to that base, and reference to the vtable, will
yield the (shared) base vtable.  Ooops, wrong type id...

Note that this is a compiler implementation detail -- an optimization that
C++ compilers use to reduce the number of vtables generated.  One could
modify the compiler to not make this optimization and generate fresh vtables
for the base portions of derived classes.  Now, if you've got your heart set
on run-time type id and you're prepared to modify the compiler, there is
no point in forcing the programmer to write useless virtual functions so
that a vtable will be generated.  The compiler can be modified to always
generate a vtable (although it may sometimes be empty).

The overhead of doing this is one word per instance of a class that would
not normally have a vtable (plus the extra vtables).

	--Charles (clark@cs.utah.edu)
From: bs@alice.att.com (Bjarne Stroustrup)
Newsgroups: comp.lang.c++
Subject: Re: New C++ type: boole
Summary: I can't spell: the widechar type is called wchar_t not w_char. Sorry
Date: 30 Jul 92 16:01:03 GMT
Article-I.D.: alice.23363
Organization: AT&T Bell Laboratories, Murray Hill NJ




The title says it all. The weird _t suffix is needed for C compatibility.
From: gordie@duts.ccc.amdahl.com (Gordon Freedman)
Newsgroups: comp.lang.c++
Subject: Re: C++ and XtAddEventHandler()
Date: 24 Jul 92 00:09:51 GMT
Reply-To: gordie@duts.ccc.amdahl.com
Organization: Happy hacker bait and tackle shop

In article 17048@nuscc.nus.sg, zhaocuie@iscs.nus.sg () writes:
>I'm using C++ to develop a GUI builder based on Motif, Xt, and X11.
>Now I'm facing some problems. I need to call an Xt convienent function
>	XtAddEventHandler(_w, event_mask, nonmaskable, proc, client_data)
>to popup Motif popup menus. I wrote the codes as follows:
>
>	void Simple::pop() {
>			......
>			XtAddEventHandler(_w,
>					  ButtonPressMask,
>					  False,
>					  &Simple::postItEventHandler,
>					  (XtPointer) this);
>			......
>			   }
>
>	void Simple::postItEventHandler(Widget, XtPointer clientData, XtPointer)
>			{
>				Simple *obj = (Simple *) clientData;
>				obj -> postIt();
>			}
>
>	void Simple::postIt() {
>			.......
>			  }
>
>It does not work. The compiler said:
>	error: bad argument 4 type for XtAddEventHandler(): void (*) (Widget,
>	XtPointer, XtPointer) (XtEventHandler expected)
>That means the type of the last argument of XtAddEventHandler() is not
>properly.
>Do you know how to call this function properly? Can anyone help me?
>
>pl. email: zhaocuie@iscs.nus.sg
>Thanks for any kind help.


You didn't include the definition of the class, but you have to declare the 
function Simple::postItEventHandler as static:

class thing 
{
private:
	static postItEventHandler (Widget, XtPointer client, XtPointer) ;
// ...
public:
// ...
} ;

Sorry if you already did this and the problem is something else, but it should
work (see "Object Oriented Programming with C++ and Motif" by Douglas A. Young
for an example of something similar using XmNdestroyCallback from within
a class - page 88).


---
Gordon Freedman: gjf00@duts.ccc.amdahl.com OOPs, did I code that?
From: vrm@hawksnest.cerc.wvu.wvnet.edu
Newsgroups: comp.lang.c++
Date: 17 Jul 92 22:45 MDT
Subject: Stroustrup's exception handling
Nf-ID: #N:VRM.92Jul17144500@hawksnest.cerc:1505554965:001:259
Nf-From: hawksnest.cerc.wvu.wvnet.edu!vrm    Jul 17 22:45:00 1992


Is there an implementation of Stroustrup's exception handling (ie.
try, throw, catch, and rethrow) available in public domain?  I would
prefer macros which use NIH EXCEPTION or strictly setjmp and longjmp,
but will accept just about anything.

Thanks, Vasile

Organization: Senior, Math/Computer Science, Carnegie Mellon, Pittsburgh, PA
Newsgroups: comp.lang.c++
Date: Mon, 27 Jul 1992 13:43:32 -0400 
From: Erik Riedel <er1p+@andrew.cmu.edu>
Subject: Re: C++ and XtAddEventHandler()


Excerpts from netnews.comp.lang.c++: 20-Jul-92 C++ and
XtAddEventHandler() by zhaocuie@iscs.nus.sg 
>I'm using C++ to develop a GUI builder based on Motif, Xt, and X11.
>Now I'm facing some problems. I need to call an Xt convienent function
>        XtAddEventHandler(_w, event_mask, nonmaskable, proc, client_data)
>to popup Motif popup menus. I wrote the codes as follows:
> 
>        void Simple::pop() {
>                        ......
>                        XtAddEventHandler(_w,
>                                          ButtonPressMask,
>                                          False,
>                                          &Simple::postItEventHandler,
>                                          (XtPointer) this);
>                        ......
>                           }
> 
>        void Simple::postItEventHandler(Widget, XtPointer clientData, XtPointe
>r)
>                        {
>                                Simple *obj = (Simple *) clientData;
>                                obj -> postIt();
>                        }
> 
>        void Simple::postIt() {
>                        .......
>                          }
> 
>It does not work. The compiler said:
>        error: bad argument 4 type for XtAddEventHandler(): void (*) (Widget,
>        XtPointer, XtPointer) (XtEventHandler expected)
>That means the type of the last argument of XtAddEventHandler() is not
>properly.
>Do you know how to call this function properly? Can anyone help me?
> 

I don't know if you've already gotten a response (a quick look ahead in
the captions shows you didn't, I'm a little behind in my new-group
reading).

I have also been working on a C++/Motif GUI.  I have been using a public
domain package called Widget Wrapper Library for most of the project
(available as WWL-1.2 on export.lcs.mit.edu for instance).  I allows the
encapsulation of widgets as C++ classes and makes the code considerably
clearer (with a small overhead payment).  It allows callback functions
to be member functions on Classes.  To solve your problem directly
however we have a macro:

#define DECLARE_METHOD_ENTRY_F(f,t,m,ca) \
void f(Widget ww,caddr_t c1,caddr_t c2){((t *)c1)->m(ww,(ca) c2) ; }

which can be used as follws:

DECLARE_METHOD_ENTRY_F (map_input_cb,Map,input_cb,XEvent *)

...

XtAddEventHandler(view_widget, ButtonPressMask, FALSE, (XtEventHandler)
map_input_cb, (XtPointer) this)
...

given the class:

class Map
{
public:
    void input_cb(Widget w,XEvent *cb);
}

----
The WWL code would reduce this to something like:

view_widget.SetInputCallback(this, (WWL_FUN)&Map::input_cb);
----

Hope this helps.

Erik Riedel
GEMS Project
Carnegie Mellon University (riedel@cmu.edu)
Massachusetts Institute of Technology (riedel@athena.mit.edu)




Newsgroups: comp.lang.c++,comp.lang.c,comp.lang.fortran
From: smcgee@nmsu.edu (Steve Mcgee)
Subject: Fortran 2 C++ conversion programs
Followup-To: poster
Organization: New Mexico State University
Date: Tue, 28 Jul 1992 19:13:15 GMT


	I just got a couple of versions of f2c to convert some archaic
FORTRAN to C++. They seem to work pretty well, save for the unappeasing
I/O libraries. Is there a FORTRAN to C(++) conversion that converts FORTRAN
READs and WRITEs to standard C(++) calls( cin, cout, fprintf, fgets etc)?

	If you know of such a beast please give me a holler.


	Steve McGee		smcgee@psl.nmsu.edu
From: 890751r@dragon.acadiau.ca (Dave Ritacco)
Subject: DJGPP - using cout
Organization: Acadia University
Date: Sat, 25 Jul 1992 19:40:46 GMT

    Finally got around to installing the GNU port of c++ to DOS and was wondering why cout doesn't seem to output anything to the screen but printf is fine....
Please email responses to ritacco@otter.phys.uvic.ca

-- 
************************************************************************
*        Dave Ritacco                Product of Acadia University      *
*           "Why don't you pull the trigger and find out?"             *
*        ritacco@otter.phys.uvic.ca                W.H.Bonney          *
Newsgroups: comp.lang.c++,comp.std.c++
From: ark@alice.att.com (Andrew Koenig)
Newsgroups: comp.lang.c++
Subject: Re: Committee Members -> What do you think?
Date: 22 Jul 92 20:27:31 GMT
Article-I.D.: alice.23281
Reply-To: ark@alice.UUCP ()
Organization: AT&T Bell Laboratories, Liberty Corner NJ

In article <1992Jul20.150341.5723@sco.COM> paul@sco.COM (Paul Jackson) writes:

> The committee does have the mandate to fix "clear" deficiencies in the
> language. Most people feel that this included templates and exception
> handling. Many people feel that it includes little else. 

The letter from Hewlett-Packard to X3 that requested formation of the
committee in the first place explicitly mentioned templates and exception
handling as being within the scope of the proposed committee.  Those two
extensions therefore have uniquely special status.
-- 
				--Andrew Koenig
				  ark@europa.att.com
Newsgroups: comp.lang.c++
From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: suggestions for global constructors
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Tue, 21 Jul 1992 16:32:23 GMT

In article <1992Jul20.115646.16161@pegasus.com> sean@pegasus.com (Sean Donovan) writes:
>In article <35736@sdcc12.ucsd.edu> skohn@cs.ucsd.edu (Scott Kohn) writes:
>>
>>Has anyone come up with any good ways of ensuring that static variables
>>are instantiated before they are used?

	They wont, ever. Because it can't be done. It is equivalent
to the halting problem.

	The best solution is to make sure there are no interdependencies.
One way to do this is to avoid global variables of external linkage.
They have very limited use anyhow.

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Xref: sparky comp.lang.c++:11443 comp.lang.c:11540
From: barmar@think.com (Barry Margolin)
Newsgroups: comp.lang.c++,comp.lang.c
Subject: Re: A Question on masking
Date: 23 Jul 1992 23:12:45 GMT
Organization: Thinking Machines Corporation, Cambridge MA, USA
NNTP-Posting-Host: telecaster.think.com

In article <1992Jul23.192147.191534@ua1ix.ua.edu> sdarbha@ho12.eng.ua.edu (Subrahmanyam Darbha) writes:
>I need to find out a single unique number for each of all [1-999][1-999][0-3]
>numbers.

/* Combine three numbers into a unique integer.
   a and b are in the range [1,999], requiring 10 bits.
   c is in [0,3], requiring 2 bits.
   Therefore, the result requires 22 bits, and we use the bit format
   aaaaaaaaaabbbbbbbbbbcc.
*/
unsigned long
combine (unsigned int a, unsigned int b, unsigned int c) {
    return (((unsigned long) a) << 12 | ((unsigned long) b) << 2 | c);
}

/* Undo the above transformation */
void
decompose (unsigned long combined,
	   unsigned int *a, unsigned int *b, unsigned int *c) {
    *a = combined >> 12;
    *b = (combined >> 2) & 0x3FF;
    *c = combined & 0x3;
}
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

barmar@think.com          {uunet,harvard}!think!barmar
Newsgroups: comp.lang.c++
From: amewaldu@cayley.waterloo.edu (Andrew Walduck)
Subject: Re: strdup() Was: Re: Renew?
Organization: University of Waterloo
Date: Thu, 30 Jul 1992 01:31:16 GMT

In article <1992Jul29.155252.7632@cbnewsk.cb.att.com> hansen@pegasus.att.com (Tony L. Hansen) writes:
>
>By the way, at least one person has posted a poor version of strdup() which
>didn't check the return value of new. Here's my contribution. As you can
>see, it is a very straightforward function:
>
>    #include <string.h>
>    char *nstrdup(const char *s)
>    {
>	if (!s) s = "";
>	char *ret = new char[strlen(s) + 1];
>	if (ret) strcpy(ret, s);
>	return ret;
>    }
>
Just remember that to delete storage allocated by this subroutine, you MUST
call delete[] and not delete...

Ie:
  char *ptr = nstrdup("Hello");
  delete []ptr; // not delete ptr;

Otherwise, things aren't guaranteed to work!! 

Andrew Walduck

Newsgroups: comp.lang.c++,comp.std.c++
From: cflatter@nrao.edu (Chris Flatters)
Subject: Re: C++ and RPC's
Reply-To: cflatter@nrao.edu
Organization: NRAO
Date: Wed, 22 Jul 1992 14:59:42 GMT

In article 11881@aostra.uucp, kreiser@aostra.uucp (Barry Kreiser) writes:
>
>Q1 - Does anyone know of C++ libraries for RPC's.  

I think that there are some C++ wrappers around the C interface.

>Q2 - Does it come with SOLARIS 2.0? 

Solaris 2 will certainly have the RPC libraries.  I imagine that they will
be TI-RPC rather than the sockets-based version used in Sun OS 4.x.  There
are minor differences between the two.

>Q3 - Is there a RPCGEN++ program anywhere?

The version of rpcgen(1) that ships with Sun C++ 2.1 takes a -C flag that
causes it to generate C++ code.  I think that this version might also ship
with the unbundled C compiler.  I assume that this is also in the SPARCworks 2
environment for Solaris 2.0.

	Chris Flatters
	cflatter@nrao.edu



Newsgroups: comp.lang.c++,comp.unix.programmer
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: How to avoid calling destructor twice after fork()?
Organization: Computer Science, University of Melbourne, Australia
Date: Thu, 30 Jul 1992 02:44:35 GMT

gyu@cis.ohio-state.edu (george yu) writes:

>I am using fork() system call in my C++ program. The problem is that each
>calling of fork() creates a copy of calling process. The problem is any
>instances created and not destroyed before fork() calling will be 
>destroyed twice. 

[I'm cross-posting to comp.unix.programmer; you might get a more informative
answer there]

When you call fork(), it creates a copy of the data space of the program
for the child. Thus parent and child each get their own copy of the stack,
heap, and static data areas.

This means that if the destructor is simply doing memory management, for
example, then the destructor *should* be called twice, since it needs to
call operator delete for both copies of the heap.

If the destructor does some I/O (eg. closing a file), then the situation
is more complicated. The simplest solution might be to bracket use of local
variables using blocks, if this is possible:

	{
	  local vars...
	  some code...
	}
	pid=fork();
	{
	  more local vars...S
	  more code...
	}

P.S.
This is related to the following problem with C programs that use fork:

	#include <stdio.h>
	extern int fork(void);

	int main(void) {
		printf("Hello");
		fork();
		printf("\n");
		return 0;
	}

You might expect this to print one "Hello" and two "\n"s.
However because stdout is buffered, the "Hello" is not printed immediately.
Thus the program forks, and then each copy contains "Hello" in the buffer
for stdio. Now when each copy prints "\n", the buffer is flushed, so you
get TWO "Hello"s as well as two "\n"s.
(The solution here is to call fflush(stdout) before calling fork().)

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature VIRUS is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!