Design of PSI
=============


The C code of psi is split in two: (i) The Python modules and classes
in src/ and (ii) the architecture or system dependent implementations
that gather the required information in src/arch/.  These two parts
communicate all the required information to each other using
structures, i.e. each class will make a call to an arch_*() function
that will return a new structure with all the required information in
for that class.

The reason for doing this is to shield the system implementations
from any Python housekeeping like reference counting.  It is hoped
that this greatly simplifies creating implementations (porting) and
reduces the risk of hidden memory leaks etc.  There is one exception
on this: error handling.  Error handling is done exactly as in Python,
i.e. you set an exception using PyErr_*(PyExc_*, ...) and then return
NULL or -1 as appropriate.  Therefore whenever a function returns NULL
or -1 you can be assured an exception is set and you need to bail out
too.

An implication of using structures to communicate between different
parts of the application is that the system implementations will have
to allocate some things like strings etc.  For this reason there are
utility functions that should always be used for memory management
purposes: psi_malloc(), psi_calloc(), psi_realloc() and psi_free(),
all defined in psi.h.  There are also more convenience functions
available in psi.h, you should definitely read this file.

Lastly the contents of the structures is important.  They are defined
in the relevant header files and should have types who's size can be
determined at compilation time to ensure that the classes and modules
will be able to convert them to the appropriate Python types (and if
not the compiler should complain).


Exceptions
----------

At Process() initialisation time only two exceptions should be raised:
(i) a ValueError if the process does not exist, (ii) SystemError if
something went wrong.

XXX Flesh this out a bit and integrate it beter where it belongs
    instead of just being a random paragraph.


C Coding Standard
-----------------

* PEP7

* Functions follow the Python convention of returning -1 or NULL in
  case of an error, in case of an error a Python exception is set.
  Testing if an `int' function was successful is best done as `if
  (some_function() < 0)' since some functions might add specific
  meanings to errors by returning a value smaller then -1
  (e.g. psi_read_file()).

* Always include <Python.h> first.  Even if nothing of python is used,
  it defines _POSIX_C_SOURCE and _XOPEN_SOURCE for us which are
  required for POSIX compliance.
