summaryrefslogtreecommitdiff
path: root/src/include/OverloadMacros.h
blob: 8f8b959c0965347bafac5560472cef22b1b88905 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 /*@@
   @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_ 1

/* 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.
 * 
 * One must also define
 *
 *  #define OVERLOADABLE_CALL prefix for calling overload functions 
 *  #define OVERLOADABLE_PREFIX prefix for real functions 
 *  #define OVERLOADABLE_DUMMY_PREFIX prefix for dummy functions
 *
 * to apply prefices to the functions.
 */

/* 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)   \
       _OVERLOADABLE_FUNCTION(OVERLOADABLE_CALL,OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_FUNCTION(call, prefix, dummy_prefix, name)   \
       __OVERLOADABLE_FUNCTION(call, prefix, dummy_prefix, name)

#define __OVERLOADABLE_FUNCTION(call, prefix, dummy_prefix, name)   \
RETURN_TYPE (*prefix##name)(ARGUMENTS) = NULL;                      \
int call##Overload##name(RETURN_TYPE (*func)(ARGUMENTS))            \
{                                                                   \
  int return_code;                                                  \
  static int overloaded = 0;                                        \
  if(overloaded < 2)                                                \
  {                                                                 \
     prefix##name = func;                                           \
     overloaded++;                                                  \
     return_code = overloaded;                                      \
  }                                                                 \
  else                                                              \
  {                                                                 \
     char *message = malloc( (200+strlen(#name))*sizeof(char) );    \
     sprintf(message,                                               \
             "Warning: Attempted to overload function %s%s twice\n",\
             #prefix, #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)   _OVERLOADABLE_PROTOTYPE(OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_PROTOTYPE(prefix, dummy_prefix, name)   __OVERLOADABLE_PROTOTYPE(prefix, dummy_prefix, name)

#define __OVERLOADABLE_PROTOTYPE(prefix, dummy_prefix, name)       \
extern RETURN_TYPE (*prefix##name)(ARGUMENTS);

/* This macro defines a dummy function */
#define OVERLOADABLE_DUMMY(name)   _OVERLOADABLE_DUMMY(OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_DUMMY(prefix, dummy_prefix, name)   __OVERLOADABLE_DUMMY(prefix, dummy_prefix, name)

#define __OVERLOADABLE_DUMMY(prefix, dummy_prefix, name)        \
RETURN_TYPE dummy_prefix##name(ARGUMENTS)                       \
{                                                               \
  fprintf(stderr, "Dummy %s%s called.\n", #dummy_prefix,#name); \
  return 0;                                                     \
}

/* This macro defines the prototype for a dummy function. */
#define OVERLOADABLE_DUMMYPROTOTYPE(name)   _OVERLOADABLE_DUMMYPROTOTYPE(OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_DUMMYPROTOTYPE(prefix, dummy_prefix, name)   __OVERLOADABLE_DUMMYPROTOTYPE(prefix, dummy_prefix, name)

#define __OVERLOADABLE_DUMMYPROTOTYPE(prefix, dummy_prefix, name)        \
RETURN_TYPE dummy_prefix##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)   _OVERLOADABLE_CHECK(OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_CHECK(prefix, dummy_prefix, name)   __OVERLOADABLE_CHECK(prefix, dummy_prefix, name)

#define __OVERLOADABLE_CHECK(prefix, dummy_prefix, name)        \
  if(!prefix##name) prefix##name = dummy_prefix##name;


/* This macro defines the prototype for the overloading function itself */

#define OVERLOADABLE_OVERLOADPROTO(name)   \
       _OVERLOADABLE_OVERLOADPROTO(OVERLOADABLE_CALL,OVERLOADABLE_PREFIX, OVERLOADABLE_DUMMY_PREFIX, name)
#define _OVERLOADABLE_OVERLOADPROTO(call,prefix, dummy_prefix, name) \
       __OVERLOADABLE_OVERLOADPROTO(call,prefix, dummy_prefix, name)

#define __OVERLOADABLE_OVERLOADPROTO(call,prefix, dummy_prefix, name)        \
int call##Overload##name(RETURN_TYPE (*func)(ARGUMENTS));


#endif /* _OVERLOADMACROS_H_ */