/* teamtrack-module.h -- Python extension interfacing to TeamTrack
   Gareth Rees, Ravenbrook Limited, 2000-08-07
   $Id: //info.ravenbrook.com/project/p4dti/branch/2000-12-07/document-history/code/python-teamtrack-interface/teamtrack-module.h#2 $

   Common definitions for the project.

   See "Python interface to TeamTrack: design"
   <master/design/python-teamtrack-interface/> for the design. */

/* Copyright 2000 Ravenbrook Limited.  This document is provided "as is",
   without any express or implied warranty. In no event will the authors
   be held liable for any damages arising from the use of this document.
   You may make and distribute copies and derivative works of this
   document provided that (1) you do not charge a fee for this document or
   for its distribution, and (2) you retain as they appear all copyright
   and licence notices and document history entries, and (3) you append
   descriptions of your modifications to the document history. */

#if !defined(TEAMTRACK_MODULE_H)
#define TEAMTRACK_MODULE_H

#include "teamtrack-python.h"
#include "TSServer.h"


/* The declaration specifier EXPORTED indicates to Visual C++ that the function
   should be exported from the DLL. */

#ifdef WIN32
#define TEAMTRACK_EXPORTED __declspec(dllexport)
#else
#define TEAMTRACK_EXPORTED
#endif


/* teamtrack_error is a Python object (in Python it's called teamtrack.error)
   that represents errors generated by this interface module. */

extern PyObject *teamtrack_error;


/* teamtrack_set_error(server) sets the current Python error to the most recent
   TeamTrack error for the given TeamShare server. */

extern void teamtrack_set_error(TSServer *server);


/* teamtrack_raise(message, result).  Raise a Python exception with
   teamtrack_error as the error object and the given message.  Return result to
   indicate that an exception has been raised. */

#define teamtrack_raise(message, result)		\
  do {							\
    PyErr_SetString(teamtrack_error, (message));	\
    return (result);					\
  } while (0)


/* teamtrack_assert(expr, result).  Evaluate expr and raise a Python exception
   if its value is zero.  Return result to indicate that an exception has been
   raised. */

#define teamtrack_stringize(x) #x

#define teamtrack_str(x) teamtrack_stringize(x)

#define teamtrack_assert(expr, result)					 \
  do {									 \
    if (!(expr)) {							 \
      teamtrack_raise("At line " teamtrack_str(__LINE__) " of " __FILE__ \
                   " the expression '" #expr "' was 0.", (result));	 \
    }									 \
  } while (0)


/* teamtrack_try(expr, server, result).  Evaluate expr and raise a Python
   exception with an appropriate message if its value is not TS_OK.  Return
   result to indicate that an exception has been raised.  The error message is
   taken from the given TeamShare server. */

#define teamtrack_try(expr, server, result)	\
  do {						\
    if ((expr) != TS_OK) {			\
      teamtrack_set_error(server);		\
      return (result);				\
    }						\
  } while (0)


/* teamtrack_check_type(classname, object, result).  Check that object belongs
   to class (by calling class_p(object)).  Raise a Python exception otherwise.
   Return reult to indicate that an exception has been raised. */

#define teamtrack_check_type(classname, object, result)	\
  do {							\
    if (!classname ## _p(object)) {			\
      PyErr_BadInternalCall();				\
      return (result);					\
    }							\
  } while (0)


#endif /* !defined(TEAMTRACK_MODULE_H) */


/* B. Document History

   2000-08-07 GDR Created.

   2000-08-08 GDR Changed error handling so that all the macros take an
   argument indicating the value to return to indicate an error (this is
   because different Python fuctions have different signatures; for example,
   the length operators returns -1 to indicate an error).  Type checking macros
   now look like ..._p instead of is_... -- this is so that all exteral
   identifiers start with ttrack_.  Macro EXPORTED now TTRACK_EXPORTED.
   ttrack_check_type now raises a BadInternalError exception when there's a
   type mismatch rather than a ttrack_error.  (This follows the practice in the
   Python implementation.)

   2000-08-23 GDR Error object ttrack_error represents errors in the Python
   interface only.  Errors in TSAPI are represented by new object
   ttrack_tsapi_error.  ttrack_set_error builds a more informative error
   message using the error code and the error message (if present).

   2000-08-29 GDR Changed "tTrack" to "TeamTrack" throughout.

*/

