summaryrefslogtreecommitdiff
path: root/spec/ffi/fixtures/FunctionTest.c
blob: 1dd918581ee7fa55f7374e936857946a8dc2a2f6 (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
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
/*
 * Copyright (c) 2007 Wayne Meissner. All rights reserved.
 *
 * For licensing, see LICENSE.SPECS
 */

#ifdef _WIN32
#include <windows.h>
#endif

#ifndef _WIN32
#include <unistd.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdlib.h>
#endif

#include "PipeHelper.h"

int testAdd(int a, int b)
{
    return a + b;
};

int testFunctionAdd(int a, int b, int (*f)(int, int))
{
    return f(a, b);
};

struct testBlockingData {
    FD_TYPE pipe1[2];
    FD_TYPE pipe2[2];
};

struct testBlockingData *testBlockingOpen()
{
    struct testBlockingData *self = malloc(sizeof(struct testBlockingData));

    if( pipeHelperCreatePipe(self->pipe1) == -1 ) return NULL;
    if( pipeHelperCreatePipe(self->pipe2) == -1 ) return NULL;
    return self;
}

char testBlockingWR(struct testBlockingData *self, char c) {
    if( pipeHelperWriteChar(self->pipe1[1], c) != 1)
        return 0;
    return pipeHelperReadChar(self->pipe2[0], 10);
}

char testBlockingRW(struct testBlockingData *self, char c) {
    char d = pipeHelperReadChar(self->pipe1[0], 10);
    if( pipeHelperWriteChar(self->pipe2[1], c) != 1)
        return 0;
    return d;
}

void testBlockingClose(struct testBlockingData *self) {
    pipeHelperClosePipe(self->pipe1[0]);
    pipeHelperClosePipe(self->pipe1[1]);
    pipeHelperClosePipe(self->pipe2[0]);
    pipeHelperClosePipe(self->pipe2[1]);
    free(self);
}

static int sum_varargs(va_list args) {
    char sum = 0;
    int arg;
    while ((arg = va_arg(args, int)) != 0) {
        sum += arg;
    }
    va_end(args);
    return sum;
}

/* Write c to pipe1 and return the value read from pipe2, or 0 if there’s
 * an error such as a timeout, or if c does not equal the sum of the
 * zero-terminated list of char arguments. */
char testBlockingWRva(struct testBlockingData *self, char c, ...) {
    va_list args;
    va_start(args, c);
    if (sum_varargs(args) != c) {
        return 0;
    }

    if( pipeHelperWriteChar(self->pipe1[1], c) != 1)
        return 0;
    return pipeHelperReadChar(self->pipe2[0], 10);
}

char testBlockingRWva(struct testBlockingData *self, char c, ...) {
    va_list args;
    va_start(args, c);
    if (sum_varargs(args) != c) {
        return 0;
    }

    char d = pipeHelperReadChar(self->pipe1[0], 10);
    if( pipeHelperWriteChar(self->pipe2[1], c) != 1)
        return 0;
    return d;
}

struct async_data {
    void (*fn)(int);
    int value;
};

static void* asyncThreadCall(void *data)
{
    struct async_data* d = (struct async_data *) data;
    if (d != NULL && d->fn != NULL) {
        (*d->fn)(d->value);
    }

    return NULL;
}

void testAsyncCallback(void (*fn)(int), int value)
{
#ifndef _WIN32
    pthread_t t;
    struct async_data d;
    d.fn = fn;
    d.value = value;
    pthread_create(&t, NULL, asyncThreadCall, &d);
    pthread_join(t, NULL);
#else
    (*fn)(value);
#endif
}

#if defined(_WIN32) && !defined(_WIN64)
struct StructUCDP {
  unsigned char a1;
  double a2;
  void *a3;
};

void __stdcall testStdcallManyParams(long *a1, char a2, short int a3, int a4, __int64 a5,
            struct StructUCDP a6, struct StructUCDP *a7, float a8, double a9) {
}
#endif