summaryrefslogtreecommitdiff
path: root/src/include/OverloadMacros.h
blob: 53b96a9afcf82069da35493836830f0ea68b58a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 /*@@
   @header    OverloadMacros.h
   @date      Thu Feb  4 08:02:29 1999
   @author    Tom Goodale
   @desc 
   Macros used for the overload functions
   @enddesc 
   @version $Header$
 @@*/

#ifndef _OVERLOADMACROS_H_
#define _OVERLOADMACROS_H_

/* These are a load of macros used to make overloadable functions. 
 *
 * Basically define ARGUMENTS with the arguments of the function,
 * and RETURN_TYPE as the return type
 * then put lines of the form OVERLOADABLE(function)
 * in a header file.
 * Defining OVERLOADABLE(name) as OVERLOADABLE_<macro>(name)
 * and then including the header will create functions, prototypes
 * dummy functions or some checking code as required.
 */

/* This macro defines a global variable with the name of the function
 * and a function which allows people to set its value.
 *
 * The function can only be called twice - to set the default, and to overload it.
 */
#define OVERLOADABLE_FUNCTION(name)                               \
RETURN_TYPE (*CCTK_##name)(ARGUMENTS) = NULL;                     \
int CCTK_Overload##name(RETURN_TYPE (*func)(ARGUMENTS))           \
{                                                                 \
  int return_code;                                                \
  static int overloaded = 0;                                      \
  if(overloaded < 2)                                              \
  {                                                               \
     CCTK_##name = func;                                          \
     overloaded++;                                                \
     return_code = overloaded;                                    \
  }                                                               \
  else                                                            \
  {                                                               \
     char *message = malloc( (200+strlen(#name))*sizeof(char) );  \
     sprintf(message,                                             \
	     "Warning: Attempted to overload function %s twice\n",\
             #name);                                              \
     CCTK_Warn(1,__LINE__,__FILE__,"Cactus",message);             \
     free(message);                                               \
     return_code = 0;                                             \
  }                                                               \
                                                                  \
  return return_code;                                             \
}

/* This macro creates an extern declaration for an overloadable function */
#define OVERLOADABLE_PROTOTYPE(name)                              \
extern RETURN_TYPE (*CCTK_##name)(ARGUMENTS);

/* This macro defines a dummy function */
#define OVERLOADABLE_DUMMY(name)                                  \
RETURN_TYPE CCTKi_Dummy##name(ARGUMENTS)                           \
{                                                                 \
  fprintf(stderr, "Dummy %s called.\n", #name);                   \
  return 0;                                                       \
}

/* This macro defines the prototype for a dummy function. */
#define OVERLOADABLE_DUMMYPROTOTYPE(name)                         \
RETURN_TYPE CCTKi_Dummy##name(ARGUMENTS);

/* This macro defines a check line which will set the overloadable
 * function to be the dummy if it hasn't been set.
 */
#define OVERLOADABLE_CHECK(name)                                  \
  if(!CCTK_##name) CCTK_##name = CCTKi_Dummy##name;


/* This macro defines the prototype for the overloading function itself */
#define OVERLOADABLE_OVERLOADPROTO(name)                          \
int CCTK_Overload##name(RETURN_TYPE (*func)(ARGUMENTS));


#endif