File: fortran_api.h

package info (click to toggle)
hdf-eos4 3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,960 kB
  • sloc: ansic: 43,570; sh: 11,324; fortran: 9,649; makefile: 261
file content (389 lines) | stat: -rw-r--r-- 21,991 bytes parent folder | download | duplicates (2)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
    Macros used to generate fortran compatible bindings for the C api.

    These macros generate customized wrapper functions based on the determined
    characteristics of the fortran compiler.

    @author Peter Smith
*/


#ifndef __FORTRAN_API_H__
#define __FORTRAN_API_H__

#include    <string.h>
#include    <stdlib.h>

/*
 * These definitions control how the fortran function name is generated. One of
 * FORTRAN_API_UPPERCASE, FORTRAN_API_LOWERCASE, or FORTRAN_API_NOCASE should be
 * defined prior to inclusion, otherwise it will will default to upper case.
 * Additionally, FORTRAN_API_PREFIX and FORTRAN_API_SUFFIX can be used to add
 * leading or trailing characters to the exported function names (e.g. underscores)
 */
#if !defined(FORTRAN_API_UPPERCASE) && !defined(FORTRAN_API_LOWERCASE) && !defined(FORTRAN_API_NOCASE)
#define FORTRAN_API_UPPERCASE 1
#endif

#ifndef FORTRAN_API_PREFIX
#define FORTRAN_API_PREFIX
#endif

#ifndef FORTRAN_API_SUFFIX
#define FORTRAN_API_SUFFIX 
#endif


/*
 * Set up the macro to select the appropriate case for naming the fortan functions.
 */
#if FORTRAN_API_UPPERCASE
#define FORTRAN_API_NAME_SELECT(a,b,c) b
#elif FORTRAN_API_LOWERCASE
#define FORTRAN_API_NAME_SELECT(a,b,c) c
#else
#define FORTRAN_API_NAME_SELECT(a,b,c) a
#endif


/*
 * Set up macros for mapping API 'types' to actual langauge types. These can be
 * prefined if necessary.
 */
#ifndef FORTRAN_API_TYPE_INT32
#define FORTRAN_API_TYPE_INT32      int
#endif

#ifndef FORTRAN_API_TYPE_INT
#define FORTRAN_API_TYPE_INT        int
#endif

#ifndef FORTRAN_API_TYPE_FLOAT64
#define FORTRAN_API_TYPE_FLOAT64    double
#endif



/************************************************************
    All configuration control is above this point. Below
    this are the code generation functions and macros.
************************************************************/

/*
 * Thunking function to map a fixed length fortran string to a c-style null
 * terminated string on input.
 */
static inline char* fortran_api_map_string_in(const char* i, unsigned FORTRAN_API_TYPE_INT maxlen) {
    unsigned FORTRAN_API_TYPE_INT len = strlen(i);
    char* o = malloc(maxlen + 1);

    len = (len < maxlen) ? len : maxlen;
    if (len == maxlen) while(len > 0 && i[len] == ' ') --len;
    memcpy(o, i, len);
    o[len] = 0;

    return o;
}

/*
 * Thunking function to map a c-style null terminated string to a fixed length fortran
 * string on output.
 */
static inline void fortran_api_map_string_out(char* o, const char* i, unsigned FORTRAN_API_TYPE_INT maxlen) {
    unsigned FORTRAN_API_TYPE_INT len = strlen(i);
    len = (len < maxlen) ? len : maxlen;
    memcpy(o, i, len);
    while(len < maxlen) o[len++] = ' ';
}


/* Nested macro expansion (needed to support MS Visual C which has a more basic preprocessor) */

#define FORTRAN_API_EXPAND(x) x

/* Join simple strings */

#define FORTRAN_API_COMBINE2(A,B) A##B
#define FORTRAN_API_COMBINE3(A,B,C) A##B##C


/*
 * Maros used to construct another macro name - for example,
 * combining a macro prefix with a number to identify a macro that takes
 * a specific number or arguments.
 */
#define FORTRAN_API_MAKENAME2(A,B) FORTRAN_API_COMBINE2(A,B)
#define FORTRAN_API_MAKENAME3(A,B,C) FORTRAN_API_COMBINE3(A,B,C)


/*
 * Macros used to expand arguments to their appropriate type in an argument list.
 */
#define FORTRAN_API_ARG_PVOID       void*
#define FORTRAN_API_ARG_STRING      const char*
#define FORTRAN_API_ARG_PSTRING     char*
#define FORTRAN_API_ARG_INT         const FORTRAN_API_TYPE_INT*
#define FORTRAN_API_ARG_PINT        FORTRAN_API_TYPE_INT*
#define FORTRAN_API_ARG_INT32       const FORTRAN_API_TYPE_INT32*
#define FORTRAN_API_ARG_PINT32      FORTRAN_API_TYPE_INT32*
#define FORTRAN_API_ARG_FLOAT64     const FORTRAN_API_TYPE_FLOAT64*
#define FORTRAN_API_ARG_PFLOAT64    FORTRAN_API_TYPE_FLOAT64*


/*
 * Macros used to map types (e.g. 'OUT STRING' => 'PSTRING'). This just provides
 * a convenience when declaring your API and makes it a bit clearer that it is an 
 * output value. 
 */
#define FORTRAN_API_TYPEMAP_OUT _,P,
#define FORTRAN_API_TYPEMAP_JOIN23(_1,_2,_3,...) _2##_3
#define FORTRAN_API_TYPEMAP_JOIN(...) FORTRAN_API_EXPAND(FORTRAN_API_TYPEMAP_JOIN23(__VA_ARGS__))

#define FORTRAN_API_TYPEMAP(type) FORTRAN_API_TYPEMAP_JOIN(FORTRAN_API_COMBINE2(FORTRAN_API_TYPEMAP_, type),,type)


/*
 * Macros used to generate argument lists. Primary arguments are prefixed with 'a', e.g.
 * a1, a2, a3, ...
 */
#define FORTRAN_API_ARG_GENERATE(type) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_ARG_,type))
#define FORTRAN_API_ARG(type,n) FORTRAN_API_ARG_GENERATE(FORTRAN_API_TYPEMAP(type)) a##n
//#define FORTRAN_API_ARG(type,n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_ARG_,type)) a##n
#define FORTRAN_API_ARGS1(t1) FORTRAN_API_ARG(t1,1)
#define FORTRAN_API_ARGS2(t1,t2) FORTRAN_API_ARGS1(t1), FORTRAN_API_ARG(t2,2)
#define FORTRAN_API_ARGS3(t1,t2,t3) FORTRAN_API_ARGS2(t1,t2), FORTRAN_API_ARG(t3,3)
#define FORTRAN_API_ARGS4(t1,t2,t3,t4) FORTRAN_API_ARGS3(t1,t2,t3), FORTRAN_API_ARG(t4,4)
#define FORTRAN_API_ARGS5(t1,t2,t3,t4,t5) FORTRAN_API_ARGS4(t1,t2,t3,t4), FORTRAN_API_ARG(t5,5)
#define FORTRAN_API_ARGS6(t1,t2,t3,t4,t5,t6) FORTRAN_API_ARGS5(t1,t2,t3,t4,t5), FORTRAN_API_ARG(t6,6)
#define FORTRAN_API_ARGS7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_ARGS6(t1,t2,t3,t4,t5,t6), FORTRAN_API_ARG(t7,7)
#define FORTRAN_API_ARGS8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_ARGS7(t1,t2,t3,t4,t5,t6,t7), FORTRAN_API_ARG(t8,8)
#define FORTRAN_API_ARGS9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_ARGS8(t1,t2,t3,t4,t5,t6,t7,t8), FORTRAN_API_ARG(t9,9)
#define FORTRAN_API_ARGS10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_ARGS9(t1,t2,t3,t4,t5,t6,t7,t8,t9), FORTRAN_API_ARG(t10,10)
#define FORTRAN_API_ARGS11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_ARGS10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10), FORTRAN_API_ARG(t11,11)
#define FORTRAN_API_ARGS12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_ARGS11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11), FORTRAN_API_ARG(t12,12)
#define FORTRAN_API_ARGS13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_ARGS12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12), FORTRAN_API_ARG(t13,13)
#define FORTRAN_API_ARGS14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_ARGS13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13), FORTRAN_API_ARG(t14,14)
#define FORTRAN_API_ARGS15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) FORTRAN_API_ARGS14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14), FORTRAN_API_ARG(t15,15)


/*
 * Macros used to generate the specific additional arguments based on the current
 * argument type. Currently, only strings do this, and these ar prefixed with 'l'
 * within an index that matches the primary argument. e.g. two string arguements
 * in position 2 and 4 would create an additional two arguments l2, l4.
 */
#define FORTRAN_API_ARGX_PVOID(n)
#define FORTRAN_API_ARGX_STRING(n)      , unsigned FORTRAN_API_TYPE_INT l##n
#define FORTRAN_API_ARGX_PSTRING(n)     , unsigned FORTRAN_API_TYPE_INT l##n
#define FORTRAN_API_ARGX_INT(n)
#define FORTRAN_API_ARGX_PINT(n)
#define FORTRAN_API_ARGX_INT32(n)
#define FORTRAN_API_ARGX_PINT32(n)
#define FORTRAN_API_ARGX_FLOAT64(n)
#define FORTRAN_API_ARGX_PFLOAT64(n)

/*
 * Macros used to generate extra arguments for input strings (in standard fortran calling
 * convention, the length of a string is passed in as an additional argument to the function)
 */
#define FORTRAN_API_ARGX_GENERATE(type, n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_ARGX_,type)(n))
#define FORTRAN_API_ARGX(type,n) FORTRAN_API_ARGX_GENERATE(FORTRAN_API_TYPEMAP(type),n)
//#define FORTRAN_API_ARGX(type,n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_ARGX_,type)(n))
#define FORTRAN_API_ARGX1(t1) FORTRAN_API_ARGX(t1,1)
#define FORTRAN_API_ARGX2(t1,t2) FORTRAN_API_ARGX1(t1) FORTRAN_API_ARGX(t2,2)
#define FORTRAN_API_ARGX3(t1,t2,t3) FORTRAN_API_ARGX2(t1,t2) FORTRAN_API_ARGX(t3,3)
#define FORTRAN_API_ARGX4(t1,t2,t3,t4) FORTRAN_API_ARGX3(t1,t2,t3) FORTRAN_API_ARGX(t4,4)
#define FORTRAN_API_ARGX5(t1,t2,t3,t4,t5) FORTRAN_API_ARGX4(t1,t2,t3,t4) FORTRAN_API_ARGX(t5,5)
#define FORTRAN_API_ARGX6(t1,t2,t3,t4,t5,t6) FORTRAN_API_ARGX5(t1,t2,t3,t4,t5) FORTRAN_API_ARGX(t6,6)
#define FORTRAN_API_ARGX7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_ARGX6(t1,t2,t3,t4,t5,t6) FORTRAN_API_ARGX(t7,7)
#define FORTRAN_API_ARGX8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_ARGX7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_ARGX(t8,8)
#define FORTRAN_API_ARGX9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_ARGX8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_ARGX(t9,9)
#define FORTRAN_API_ARGX10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_ARGX9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_ARGX(t10,10)
#define FORTRAN_API_ARGX11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_ARGX10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_ARGX(t11,11)
#define FORTRAN_API_ARGX12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_ARGX11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_ARGX(t12,12)
#define FORTRAN_API_ARGX13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_ARGX12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_ARGX(t13,13)
#define FORTRAN_API_ARGX14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_ARGX13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_ARGX(t14,14)
#define FORTRAN_API_ARGX15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) FORTRAN_API_ARGX14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_ARGX(t15,15)



/*
 * Macros used to expand input arguments to their appropriate type in the internal API function call.
 * Everything in FORTRAN is passed by reference (pointer), so we need to dereference values such as
 * integers or floats, but not arrays.
 */
#define FORTRAN_API_PARAM_PVOID(n)      a##n
#define FORTRAN_API_PARAM_STRING(n)     _a##n
#define FORTRAN_API_PARAM_PSTRING(n)    _a##n
#define FORTRAN_API_PARAM_INT(n)        *a##n
#define FORTRAN_API_PARAM_PINT(n)       a##n
#define FORTRAN_API_PARAM_INT32(n)      *a##n
#define FORTRAN_API_PARAM_PINT32(n)     a##n
#define FORTRAN_API_PARAM_FLOAT64(n)    *a##n
#define FORTRAN_API_PARAM_PFLOAT64(n)   a##n


/*
 * Macros used to generate parameter lists for invoking the internal function
 */
#define FORTRAN_API_PARAM_GENERATE(type, n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_PARAM_,type)(n))
#define FORTRAN_API_PARAM(type,n) FORTRAN_API_PARAM_GENERATE(FORTRAN_API_TYPEMAP(type),n)
//#define FORTRAN_API_PARAM(type,n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_PARAM_,type)(n))
#define FORTRAN_API_PARAMS1(t1) FORTRAN_API_PARAM(t1,1)
#define FORTRAN_API_PARAMS2(t1,t2) FORTRAN_API_PARAMS1(t1), FORTRAN_API_PARAM(t2,2)
#define FORTRAN_API_PARAMS3(t1,t2,t3) FORTRAN_API_PARAMS2(t1,t2), FORTRAN_API_PARAM(t3,3)
#define FORTRAN_API_PARAMS4(t1,t2,t3,t4) FORTRAN_API_PARAMS3(t1,t2,t3), FORTRAN_API_PARAM(t4,4)
#define FORTRAN_API_PARAMS5(t1,t2,t3,t4,t5) FORTRAN_API_PARAMS4(t1,t2,t3,t4), FORTRAN_API_PARAM(t5,5)
#define FORTRAN_API_PARAMS6(t1,t2,t3,t4,t5,t6) FORTRAN_API_PARAMS5(t1,t2,t3,t4,t5), FORTRAN_API_PARAM(t6,6)
#define FORTRAN_API_PARAMS7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_PARAMS6(t1,t2,t3,t4,t5,t6), FORTRAN_API_PARAM(t7,7)
#define FORTRAN_API_PARAMS8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_PARAMS7(t1,t2,t3,t4,t5,t6,t7), FORTRAN_API_PARAM(t8,8)
#define FORTRAN_API_PARAMS9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_PARAMS8(t1,t2,t3,t4,t5,t6,t7,t8), FORTRAN_API_PARAM(t9,9)
#define FORTRAN_API_PARAMS10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_PARAMS9(t1,t2,t3,t4,t5,t6,t7,t8,t9), FORTRAN_API_PARAM(t10,10)
#define FORTRAN_API_PARAMS11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_PARAMS10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10), FORTRAN_API_PARAM(t11,11)
#define FORTRAN_API_PARAMS12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_PARAMS11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11), FORTRAN_API_PARAM(t12,12)
#define FORTRAN_API_PARAMS13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_PARAMS12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12), FORTRAN_API_PARAM(t13,13)
#define FORTRAN_API_PARAMS14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_PARAMS13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13), FORTRAN_API_PARAM(t14,14)
#define FORTRAN_API_PARAMS15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) FORTRAN_API_PARAMS14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14), FORTRAN_API_PARAM(t15,15)



/*
 * Macros used to generate mapping code for input parameters (code that converts an input value
 * to something that can be passed through to the API function call). Generally, only strings need
 * mapping code since FORTRAN uses fixed length strings where the length is passed in as an
 * additional function argument. Note that string handling is currently NOT optimized, but the likely
 * overhead is small when compared to the processing that is likely being performed on the data.
 */
#define FORTRAN_API_MAP_IN_PVOID(n)
#define FORTRAN_API_MAP_IN_STRING(n)        char* _a##n = fortran_api_map_string_in(a##n, l##n);
#define FORTRAN_API_MAP_IN_PSTRING(n)       char* _a##n = fortran_api_map_string_in(a##n, l##n);
#define FORTRAN_API_MAP_IN_INT(n)
#define FORTRAN_API_MAP_IN_PINT(n)
#define FORTRAN_API_MAP_IN_INT32(n)
#define FORTRAN_API_MAP_IN_PINT32(n)
#define FORTRAN_API_MAP_IN_FLOAT64(n)
#define FORTRAN_API_MAP_IN_PFLOAT64(n)


/*
 * Macros used to generate extra argument lists
 */
#define FORTRAN_API_MAP_IN_GENERATE(type, n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_MAP_IN_,type)(n)) 
#define FORTRAN_API_MAP_IN(type,n) FORTRAN_API_MAP_IN_GENERATE(FORTRAN_API_TYPEMAP(type), n)
//#define FORTRAN_API_MAP_IN(type,n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_MAP_IN_,type)(n)) 
#define FORTRAN_API_MAP_IN1(t1) FORTRAN_API_MAP_IN(t1,1)
#define FORTRAN_API_MAP_IN2(t1,t2) FORTRAN_API_MAP_IN1(t1) FORTRAN_API_MAP_IN(t2,2)
#define FORTRAN_API_MAP_IN3(t1,t2,t3) FORTRAN_API_MAP_IN2(t1,t2) FORTRAN_API_MAP_IN(t3,3)
#define FORTRAN_API_MAP_IN4(t1,t2,t3,t4) FORTRAN_API_MAP_IN3(t1,t2,t3) FORTRAN_API_MAP_IN(t4,4)
#define FORTRAN_API_MAP_IN5(t1,t2,t3,t4,t5) FORTRAN_API_MAP_IN4(t1,t2,t3,t4) FORTRAN_API_MAP_IN(t5,5)
#define FORTRAN_API_MAP_IN6(t1,t2,t3,t4,t5,t6) FORTRAN_API_MAP_IN5(t1,t2,t3,t4,t5) FORTRAN_API_MAP_IN(t6,6)
#define FORTRAN_API_MAP_IN7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_MAP_IN6(t1,t2,t3,t4,t5,t6) FORTRAN_API_MAP_IN(t7,7)
#define FORTRAN_API_MAP_IN8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_MAP_IN7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_MAP_IN(t8,8)
#define FORTRAN_API_MAP_IN9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_MAP_IN8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_MAP_IN(t9,9)
#define FORTRAN_API_MAP_IN10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_MAP_IN9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_MAP_IN(t10,10)
#define FORTRAN_API_MAP_IN11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_MAP_IN10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_MAP_IN(t11,11)
#define FORTRAN_API_MAP_IN12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_MAP_IN11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_MAP_IN(t12,12)
#define FORTRAN_API_MAP_IN13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_MAP_IN12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_MAP_IN(t13,13)
#define FORTRAN_API_MAP_IN14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_MAP_IN13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_MAP_IN(t14,14)
#define FORTRAN_API_MAP_IN15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) FORTRAN_API_MAP_IN14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_MAP_IN(t15,15)



/*
 * Macros used to generate mapping code for output parameters. Generally, only strings need
 * mapping code since FORTRAN uses fixed length strings where the length is passed in as an
 * additional function argument. 
 */
#define FORTRAN_API_MAP_OUT_PVOID(n)
#define FORTRAN_API_MAP_OUT_STRING(n) free(_a##n);
#define FORTRAN_API_MAP_OUT_PSTRING(n)  fortran_api_map_string_out(a##n, _a##n, l##n); FORTRAN_API_MAP_OUT_STRING(n)
#define FORTRAN_API_MAP_OUT_INT(n)
#define FORTRAN_API_MAP_OUT_PINT(n)
#define FORTRAN_API_MAP_OUT_INT32(n)
#define FORTRAN_API_MAP_OUT_PINT32(n)
#define FORTRAN_API_MAP_OUT_FLOAT64(n)
#define FORTRAN_API_MAP_OUT_PFLOAT64(n)


/*
 * Macros used to generate extra argument lists
 */
#define FORTRAN_API_MAP_OUT_GENERATE(type, n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_MAP_OUT_,type)(n)) 
#define FORTRAN_API_MAP_OUT(type,n) FORTRAN_API_MAP_OUT_GENERATE(FORTRAN_API_TYPEMAP(type), n)
//#define FORTRAN_API_MAP_OUT(type,n) FORTRAN_API_EXPAND(FORTRAN_API_COMBINE2(FORTRAN_API_MAP_OUT_,type)(n)) 
#define FORTRAN_API_MAP_OUT1(t1) FORTRAN_API_MAP_OUT(t1,1)
#define FORTRAN_API_MAP_OUT2(t1,t2) FORTRAN_API_MAP_OUT1(t1) FORTRAN_API_MAP_OUT(t2,2)
#define FORTRAN_API_MAP_OUT3(t1,t2,t3) FORTRAN_API_MAP_OUT2(t1,t2) FORTRAN_API_MAP_OUT(t3,3)
#define FORTRAN_API_MAP_OUT4(t1,t2,t3,t4) FORTRAN_API_MAP_OUT3(t1,t2,t3) FORTRAN_API_MAP_OUT(t4,4)
#define FORTRAN_API_MAP_OUT5(t1,t2,t3,t4,t5) FORTRAN_API_MAP_OUT4(t1,t2,t3,t4) FORTRAN_API_MAP_OUT(t5,5)
#define FORTRAN_API_MAP_OUT6(t1,t2,t3,t4,t5,t6) FORTRAN_API_MAP_OUT5(t1,t2,t3,t4,t5) FORTRAN_API_MAP_OUT(t6,6)
#define FORTRAN_API_MAP_OUT7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_MAP_OUT6(t1,t2,t3,t4,t5,t6) FORTRAN_API_MAP_OUT(t7,7)
#define FORTRAN_API_MAP_OUT8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_MAP_OUT7(t1,t2,t3,t4,t5,t6,t7) FORTRAN_API_MAP_OUT(t8,8)
#define FORTRAN_API_MAP_OUT9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_MAP_OUT8(t1,t2,t3,t4,t5,t6,t7,t8) FORTRAN_API_MAP_OUT(t9,9)
#define FORTRAN_API_MAP_OUT10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_MAP_OUT9(t1,t2,t3,t4,t5,t6,t7,t8,t9) FORTRAN_API_MAP_OUT(t10,10)
#define FORTRAN_API_MAP_OUT11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_MAP_OUT10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) FORTRAN_API_MAP_OUT(t11,11)
#define FORTRAN_API_MAP_OUT12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_MAP_OUT11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) FORTRAN_API_MAP_OUT(t12,12)
#define FORTRAN_API_MAP_OUT13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_MAP_OUT12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) FORTRAN_API_MAP_OUT(t13,13)
#define FORTRAN_API_MAP_OUT14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_MAP_OUT13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) FORTRAN_API_MAP_OUT(t14,14)
#define FORTRAN_API_MAP_OUT15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) FORTRAN_API_MAP_OUT14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) FORTRAN_API_MAP_OUT(t15,15)


/*
 * Macros used to count the number of args/parameters in a list. This can handle lists 
 * of up to 15 values. This is the key to allowing a single API declaration macro that
 * can handle variable length argument lists.
 */
#define FORTRAN_API_COUNT_LIST(...) FORTRAN_API_EXPAND(FORTRAN_API_CHECK_LIST(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define FORTRAN_API_CHECK_LIST(_1,_2_,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,N,...) N


/*
 * Macros used to automtically create the appropriate argument or parameter list
 * based on the number of arguments.
 */
#define FORTRAN_API_MACRO_NAME(name,...) FORTRAN_API_MAKENAME2(name,FORTRAN_API_COUNT_LIST(__VA_ARGS__)) 
#define FORTRAN_API_ARG_LIST(...) FORTRAN_API_EXPAND(FORTRAN_API_MACRO_NAME(FORTRAN_API_ARGS,__VA_ARGS__)(__VA_ARGS__)) FORTRAN_API_EXPAND(FORTRAN_API_MACRO_NAME(FORTRAN_API_ARGX,__VA_ARGS__)(__VA_ARGS__))
#define FORTRAN_API_PARAM_LIST(...) FORTRAN_API_EXPAND(FORTRAN_API_MACRO_NAME(FORTRAN_API_PARAMS,__VA_ARGS__)(__VA_ARGS__))


/*
 * Macros used to handle return values. There are two aspects to this. The first is to
 * capture a return value from the internal function call. The second is to return
 * the value to the caller. 'void' is the special case here, since it indicates no
 * return value. These macros use a special case to generate a list of different
 * lengths, depending upon whether the return type is VOID or not, allowing us to
 * pick the value we want from a known position.
 */
#define FORTRAN_API_CAPTURE_RETURN_VOID _,

#define FORTRAN_API_SELECT_2(_1,_2,...) _2
#define FORTRAN_API_SELECT_RETURN(...) FORTRAN_API_EXPAND(FORTRAN_API_SELECT_2(__VA_ARGS__))

#define FORTRAN_API_CAPTURE_RETURN(type) FORTRAN_API_SELECT_RETURN(FORTRAN_API_COMBINE2(FORTRAN_API_CAPTURE_RETURN_,type),FORTRAN_API_COMBINE2(FORTRAN_API_TYPE_,type) retval =)
#define FORTRAN_API_RETURN(type) FORTRAN_API_SELECT_RETURN(FORTRAN_API_COMBINE2(FORTRAN_API_CAPTURE_RETURN_,type), return retval;)



/*
 * Macro to generate a fortran based wrapper function. This is the macro used to declare API
 * functions and automatically generate the wrapper code. Arguments are as follows:
 *  rettype     The function return type (INT32, FLOAT64, VOID, etc)
 *  name        The function name exactly as defined in the C code
 *  uc          The upper case form of the function name (macros cannot do this case conversion)
 *  lc          The lower case form of the function name
 *  ...         Additional parameter arguments (INT32, FLOAT64, STRING, etc )
 */
#define FORTRAN_API_FN(rettype, name, uc, lc, ...)                                                      \
    FORTRAN_API_COMBINE2(FORTRAN_API_TYPE_,rettype)                                                     \
    FORTRAN_API_MAKENAME3(FORTRAN_API_PREFIX,FORTRAN_API_NAME_SELECT(name,uc,lc),FORTRAN_API_SUFFIX)    \
    (FORTRAN_API_ARG_LIST(__VA_ARGS__))                                                                 \
    {                                                                                                   \
        FORTRAN_API_EXPAND(FORTRAN_API_MACRO_NAME(FORTRAN_API_MAP_IN,__VA_ARGS__)(__VA_ARGS__))         \
        FORTRAN_API_CAPTURE_RETURN(rettype) name(FORTRAN_API_PARAM_LIST(__VA_ARGS__));                  \
        FORTRAN_API_EXPAND(FORTRAN_API_MACRO_NAME(FORTRAN_API_MAP_OUT,__VA_ARGS__)(__VA_ARGS__))        \
        FORTRAN_API_RETURN(rettype)                                                                     \
    }



#endif   // __FORTRAN_API_H__