Notes on libpawlib2-dev
-----------------------

1) This package does not include the Lesstif-dependent parts of Pawlib.
Those can be found in the package libpawlib-lesstif3-dev.


2) Note that much of this library is functional on 64-bit machines only when
statically linked.  Please see the file README.64-bit for more information.
An example illustrating some other things to take care about is given
in /usr/share/doc/libpawlib2-dev/examples/comis-64bit-example.F .


3) On 32-bit architectures, please read this note carefully if you link against
pawlib dynamically so that the COMIS interpreter works correctly in your
application.  This is especially applicable if your application dies with this
error message:

	CSALLO: heap below bss?!

If you link statically, this note does not concern you.  The default output of
the "cernlib" script includes the -static compiler flag, so a program linked
via a command like one of these:

	gfortran myprogram.F -o myprogram `cernlib pawlib`
	gcc file1.o file2.o file3.o -o myprogram `cernlib pawlib`

is statically linked to pawlib.

If you have doubts, run ldd on your executable; a statically linked program
should NOT have the output of ldd include a line similar to this:

	libpawlib.so.2 => /usr/lib/*/libpawlib.so.2 (0x0f7eb000)

Executive summary
-----------------

a) If your executable's main source code file is written in FORTRAN, it should

	#include <comis/mdpool.inc>

immediately after the "      PROGRAM programname" line.

b) If your executable's main source code file is written in C or C++, it should

	#include <comis/mdpool.h>

at the top of the source code.

It is only necessary for one file of your source code to include mdpool.inc or
mdpool.h, and may in fact cause linking problems if more than one file does so.
Do not include mdpool.inc or mdpool.h in a header file unless that file is
itself only #included by one source file.

Technical details
-----------------

The authors of COMIS (the PAW interpreter) used two memory allocation areas;
one is the integer array IQ (size: 50006 integers) in the COMMON block MDPOOL,
and the other is dynamically allocated by malloc() in the CSALLO function.  The
difference between the malloc()ed pointer address and the address of the common
block is returned to FORTRAN code, so it can access the new memory by using the
appropriate array subscript in MDPOOL/IQ.

The idea is similar to that expressed in the following C code:

#include <stdlib.h>

typedef struct { int iq[50006]; } mdpool_def;
mdpool_def mdpool;

int main()
{
  unsigned long iqpntr = (unsigned long)mdpool.iq;
  unsigned long lpntr  = (unsigned long)malloc(sizeof(int));
  int           index  = (lpntr - iqpntr) / sizeof(int);

  mdpool.iq[index] = 5;
  return mdpool.iq[index];
}

The problem is that the FORTRAN code in pawlib expects the address difference
(the variable "index" in the above example) to be positive.  This is fine when
an executable is statically linked to pawlib, since then the malloc()ed space
in the heap is always at a larger address than MDPOOL in the binary's bss
segment.  But on some (most?) architectures, shared libraries, including MDPOOL
in libpawlib.so, are mapped into memory beyond the program stack, yielding a
negative address offset.

After a lot of trying, I concluded that tracking down all the places in the
FORTRAN code that expected a positive pointer offset from MDPOOL would be very
difficult and error-prone, so the solution is to attack the problem from the
other end.  That is, declare MDPOOL/IQ in the dynamically linked executable.
Then MDPOOL will always be present in these executables' bss segments, whose
address is always less than that of space allocated on the heap.  This is
accomplished by #include'ing <comis/mdpool.inc> or <comis/mdpool.h> in the
source code for the executable.  See, e.g., the file
/usr/share/doc/libpawlib2-dev/examples/pamain.c .

-- Kevin McCarty <kmccarty@debian.org>, Mon, 29 Nov 2004
