Affix

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
This function will parse a pointer into a given target type.
 
The source pointer would have normally been obtained from a call to a native
subroutine that returned a pointer, a lvalue pointer to a native subroutine,
or, as part of a `Struct[ ... ]`.
 
## `DumpHex( ... )`
 
```
DumpHex( $ptr, $length );
```
 
Dumps `$length` bytes of raw data from a given point in memory.
 
This is a debugging function that probably shouldn't find its way into your
code and might not be public in the future.
 
# Types
 
Raku offers a set of native types with a fixed, and known, representation in
memory but this is Perl so we need to do the work ourselves with a pseudo-type
system. Affix supports the fundamental types (void, int, etc.), aggregates
(struct, array, union), and .

README.md  view on Meta::CPAN

628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
    year  => Int
];
```
 
All fundamental and aggregate types may be found inside of a `Struct`.
 
## `ArrayRef[ ... ]`
 
The elements of the array must pass the additional size constraint.
 
An array length must be given:
 
```
ArrayRef[Int, 5];   # int arr[5]
ArrayRef[Any, 20];  # SV * arr[20]
ArrayRef[Char, 5];  # char arr[5]
ArrayRef[Str, 10];  # char *arr[10]
```
 
## `Union[ ... ]`

builder/Affix.pm  view on Meta::CPAN

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
my $response = $http->get('https://dyncall.org/download');
die sprintf "Failed to download %s: %s!", $response->{url}, $response->{content}
    unless $response->{success};
 
#print "$response->{status} $response->{reason}\n";
#while ( my ( $k, $v ) = each %{ $response->{headers} } ) {
#    for ( ref $v eq 'ARRAY' ? @$v : $v ) {
#        print "$k: $_\n";
#    }
#}
#print $response->{content} if length $response->{content};
if ( $opt{config}->get('osname') eq 'MSWin32' ) {    # Use prebuilt libs on Windows
    my $x64  = $opt{config}->get('ptrsize') == 8;
    my $plat = $x64 ? '64' : '86';
    my %versions;
    for my $url ( map { 'https://dyncall.org/' . $_ }
        $response->{content}
        =~ m[href="(.+/dyncall-\d\.\d+\-windows-xp-x${plat}(?:-r)?\.zip)"]g ) {

dyncall/configure  view on Meta::CPAN

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    printf "AR=psp-ar\n"  >>$C
    printf "CFLAGS=-I${SDKROOT}/include/\n" >>$C
    printf "CXXFLAGS=-I${SDKROOT}/include/\n" >>$C
    # Pulling in dyncall libs below is a hack, for some reason psp-ld is super-picky about order.
    # Use your C lib of choice, from the PSPSDK, or...
    #printf "LDLIBS=-L${SDKROOT}/lib/ -L${SRCTOP}/dyncall -L${SRCTOP}/dyncallback -ldyncall_s -ldyncallback_s -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lstdc++ -lpsplibc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputili...
    # ... newlib.
    printf "LDLIBS=-L${SDKROOT}/lib/ -L${SRCTOP}/dyncall -L${SRCTOP}/dyncallback -ldyncall_s -ldyncallback_s -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lstdc++ -lc       -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputilit...
    ;;
  ?)
    cat $0 | awk '/^esac$/{b=0}/^  [A-Za-z0-9|]+\)/{if(b==1) print substr($1,1,length($1)-1)}BEGIN{b=0}/^case.*TARGET.*uname.*in$/{b=1}' | tr '|' '\n'
    exit 0
    ;;
esac
 
 
# removed, b/c platform support not consistent and ELF flags checked often not having any result
#
## Assure objects not asking for an execstack (or binary that links dyncall might end
## up with one, for no reason).
#

dyncall/doc/manual/manual.tex  view on Meta::CPAN

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
% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%
%//////////////////////////////////////////////////////////////////////////////
 
% Set the normal line height for the entire document (some command depend on it).
\newcommand{\normallineheight}{10pt}
\documentclass[\normallineheight,a4paper]{article}
 
 
% Value multiplier.
\newlength\mrbraceheight
\newcommand{\tassimultiply}[2]{%
\setlength{\mrbraceheight}{0pt}%
\newcount\qq%
\qq=1   % Subtract 1 by starting at 1 .
\loop%
        \addtolength\mrbraceheight{#2}%
        \advance\qq by 1%
\ifnum\qq < #1 \repeat%
}
 
 
% Conditional if tex4ht is on or not
\newcommand{\ifhtml}[1]{%
        \ifx\HCode\Undef \else%
                #1%
        \fi%

dyncall/doc/manual/manual.tex  view on Meta::CPAN

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
\newcommand{\shell}[1]{\noindent{\tt #1}}
 
% Multiline table row with left or right curly brace.
%\newcommand{\mrrbrace}[2]{\tassimultiply{#1}{5pt} \multirow{#1}{*}{$\smash{\left. {\vrule height 0pt depth \mrbraceheight width 0pt}\right\}}$#2}}
\newcommand{\mrrbrace}[2]{\rdelim\}{#1}{\normallineheight} \multirow{#1}{*}{#2}                                 }
\newcommand{\mrlbrace}[2]{                                 \multirow{#1}{*}{#2} \ldelim\{{#1}{\normallineheight}}
 
 
\newcommand{\tablewidth}{130mm}
%\setlength{\oddsidemargin}{10mm}
%\setlength{\textwidth}{140mm}
%\setlength{\parindent}{0mm}
%\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
 
\newcommand{\ninety}[1]{\begin{sideways}#1\end{sideways}}
 
\renewcommand{\paragraph}[1]{%
        \par\vspace{12pt}%
        \noindent%
        \textbf{#1}%
        \par%
        \vspace{6pt}%
}%
 
% Set a watermark, but not when running htlatex
\ifnhtml{%
\watermark{%
\begingroup%
\setlength{\unitlength}{1mm}%
\begin{picture}(0,0)(32,300)%
        \includegraphics[scale=1.0]{dyncall_watermark}%
\end{picture}%
\endgroup%
}%
}
 
 
% Use a sans-serif font.
\renewcommand{\familydefault}{\sfdefault}

dyncall/doc/manual/manual_title.tex  view on Meta::CPAN

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
% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%
%//////////////////////////////////////////////////////////////////////////////
 
\newcommand{\dyncallversion}{1.4}
\newcommand{\titlelogo}{%
\begingroup%
\setlength{\unitlength}{1mm}%
\begin{picture}(0,0)(-38,110)%
\includegraphics[scale=0.35]{dyncall_logo}%
\end{picture}%
\endgroup%
%\begingroup
%\setlength{\unitlength}{1bp}%
%\begin{picture}(250,400)%
%\end{picture}%
%\endgroup
%
%
%\setlength{\unitlength}{1mm}
%\begin{picture}(60, 40)
%\put(42,31){\circle*{1}}
%\put(42,30){\circle{2}}
%\put(40,31){\circle{4}}
%\put(40,30){\circle{8}}
%\put(41,31){\circle{16}}
%\put(41,30){\circle{32}}
%\put(19,31){\circle{1}}
%\put(20,30){\circle*{2}}
%\put(21,31){\circle{3}}

dyncall/dyncall/dyncall_vector.h  view on Meta::CPAN

41
42
43
44
45
46
47
48
49
50
51
52
53
#define dcVecInit(p,size)   (p)->mTotal=size;(p)->mSize=0
#define dcVecReset(p)       (p)->mSize=0
#define dcVecResize(p,size) (p)->mSize=(size)
#define dcVecSkip(p,size)   (p)->mSize+=(size)
#define dcVecData(p)        ( (unsigned char*) (((DCVecHead*)(p))+1) )
#define dcVecAt(p,index)    ( dcVecData(p)+index )
#define dcVecSize(p)        ( (p)->mSize )
#define dcVecAlign(p,align) (p)->mSize=( (p)->mSize + align-1 ) & -align
 
 
void dcVecAppend(DCVecHead* pHead, const void* source, size_t length);
 
#endif /* DC_VECTOR_H */

dyncall/dynload/dynload_unix.c  view on Meta::CPAN

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* for dlopen-based dlGetLibraryPath impls below, prefer RTLD_NOLOAD that
 * merely checks lib names */
#if defined(RTLD_NOLOAD)
#  define RTLD_LIGHTEST RTLD_LAZY|RTLD_NOLOAD
#else
#  define RTLD_LIGHTEST RTLD_LAZY
#endif
 
 
/* helper copying string if buffer big enough, returning length (without \0) */
static int dl_strlen_strcpy(char* dst, const char* src, int dstSize)
{
  int l = strlen(src);
  if(l < dstSize) /* l+'\0' <= bufSize */
    strcpy(dst, src);
  return l;
}
 
/* code for dlGetLibraryPath() is platform specific */

dyncall/dynload/dynload_windows.c  view on Meta::CPAN

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
void dlFreeLibrary(DLLib* pLib)
{
  FreeLibrary((HINSTANCE)pLib);
}
 
 
int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize)
{
  /* get the path name as wide chars, then convert to UTF-8; we need   */
  /* some trial and error to figure out needed wide char string length */
 
  wchar_t* ws;
  int r;
 
  /* num chars to alloc temp space for, and upper limit, must be both power */
  /* of 2s for loop to be precise and to test allow testing up to 32768 chars */
  /* (including \0), which is the extended path ("\\?\...") maximum */
  static const int MAX_EXT_PATH = 1<<15; /* max extended path length (32768) */
  int nc = 1<<6;                         /* guess start buffer size, */
 
  while(nc <= MAX_EXT_PATH)/*@@@ add testcode for super long paths*/
  {
    ws = (wchar_t*)dlAllocMem(nc * sizeof(wchar_t));
    if(!ws)
      break;
 
    r = GetModuleFileNameW((HMODULE)pLib, ws, nc);

eg/Cookbook/xor_cipher.pl  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use YAML();
use Affix;
affix './xor_cipher.so', 'string_crypt_free', [ Pointer [Void] ], Void;
 
sub string_crypt {
    CORE::state $string_crypt //= wrap './xor_cipher.so', 'string_crypt', [ Str, Int, Str ],
        Pointer [Char];
    my ( $input, $key ) = @_;
    my $ptr = $string_crypt->( $input, length($input), $key );
    my $out = $ptr->raw( length $input );
    string_crypt_free($ptr);
    $out;
}
#
my $orig = "hello world";
my $key  = "foobar";
print YAML::Dump($orig);
my $encrypted = string_crypt( $orig, $key );
print YAML::Dump($encrypted);
my $decrypted = string_crypt( $encrypted, $key );

lib/Affix.pm  view on Meta::CPAN

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
my $vp = 0;    # void *
 
sub _mangle_name ($$) {
    my ( $func, $name ) = @_;
    if ( grep { $_ eq $name } @cache ) {
        return join '', 'S', ( grep { $cache[$_] eq $name } 0 .. $#cache ), '_';
    }
    push @cache, $name;
    $name =~ s[^$func][S0_];
    sprintf $name =~ '::' ? 'N%sE' : '%s',
        join( '', ( map { length($_) . $_ } split '::', $name ) );
}
 
sub _mangle_type {
    my ( $func, $type ) = @_;
    return    #'A'
        'P' . _mangle_type( $func, $type->{type} ) if $type->isa('Affix::Type::ArrayRef');
    if ( $type->isa('Affix::Type::Pointer') && $type->{type}->isa('Affix::Type::Void') ) {
        return $vp++ ? 'S_' : 'Pv';
    }
    return 'P' . _mangle_type( $func, $type->{type} ) if $type->isa('Affix::Type::Pointer');

lib/Affix.pm  view on Meta::CPAN

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
        WChar(), 'w', LongLong(), 'x', ULongLong(), 'y', '_', '',    # Calling conventions
    };
    $types->{$type} // die 'Unknown type: ' . $type;
}
 
sub Itanium_mangle {
    my ( $lib, $name, $affix ) = @_;
    @cache = ();
    $vp    = 0;
    my $ret = '_Z' . sprintf $name =~ '::' ? 'N%sE' : '%s',
        join( '', ( map { length($_) . $_ } split '::', $name ) );
 
    #~ for my $arg ( scalar @{ $affix->{args} } ? @{ $affix->{args} } : Void() ) {
    my @args = scalar @{$affix} ? @{$affix} : Void();
    while (@args) {
        my $arg = shift @args;
        $ret .= _mangle_type( $name, $arg );
        if ( $arg eq '_' ) {
            shift @args;
            push @args, Void() if !@args;    # skip calling conventions
        }

lib/Affix.pm  view on Meta::CPAN

341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
        # legacy
        sub Rust_legacy_mangle {
            my ( $lib, $name, $affix ) = @_;
            CORE::state $symbol_cache //= ();
            $symbol_cache->{$lib} //= Affix::_list_symbols($lib);
            @cache = ();
            $vp    = 0;
            return $name if grep { $name eq $_ } grep { defined $_ } @{ $symbol_cache->{$lib} };
            my $ret = qr'^_ZN(?:\d+\w+?)?' . sprintf $name =~ '::' ? '%sE' : '%s17h\w{16}E$',
                join( '', ( map { length($_) . $_ } split '::', $name ) );
            my @symbols = grep { $_ =~ $ret } grep { defined $_ } @{ $symbol_cache->{$lib} };
            return shift @symbols;
        }
    }
};
1;
__END__
 
=encoding utf-8

lib/Affix.pm  view on Meta::CPAN

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
    my $hash = cast( $ptr, Struct[i => Int, ... ] );
 
This function will parse a pointer into a given target type.
 
The source pointer would have normally been obtained from a call to a native
subroutine that returned a pointer, a lvalue pointer to a native subroutine,
or, as part of a C<Struct[ ... ]>.
 
=head2 C<DumpHex( ... )>
 
    DumpHex( $ptr, $length );
 
Dumps C<$length> bytes of raw data from a given point in memory.
 
This is a debugging function that probably shouldn't find its way into your
code and might not be public in the future.
 
=head1 Types
 
Raku offers a set of native types with a fixed, and known, representation in
memory but this is Perl so we need to do the work ourselves with a pseudo-type
system. Affix supports the fundamental types (void, int, etc.), aggregates
(struct, array, union), and .

lib/Affix.pm  view on Meta::CPAN

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
        model => Str,
        year  => Int
    ];
 
All fundamental and aggregate types may be found inside of a C<Struct>.
 
=head2 C<ArrayRef[ ... ]>
 
The elements of the array must pass the additional size constraint.
 
An array length must be given:
 
    ArrayRef[Int, 5];   # int arr[5]
    ArrayRef[Any, 20];  # SV * arr[20]
    ArrayRef[Char, 5];  # char arr[5]
    ArrayRef[Str, 10];  # char *arr[10]
 
=head2 C<Union[ ... ]>
 
A union is a type consisting of a sequence of members with overlapping storage
(as opposed to C<Struct>, which is a type consisting of a sequence of members

lib/Affix.xs  view on Meta::CPAN

1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
            }
            av_push(values, newSVsv(TARGET));
        }
        sv_inc(current_value);
    }
    hv_stores(RETVAL_HV, "values", newRV_inc(MUTABLE_SV(values)));
}; break;
case DC_SIGCHAR_ARRAY: { // ArrayRef[Int, 5]
    AV *type_size = MUTABLE_AV(SvRV(ST(1)));
    SV *type, *size;
    size_t array_length, array_sizeof = 0;
    bool packed = false;
    switch (av_count(type_size)) {
    case 1: {
        size = newSV(1);
        type = *av_fetch(type_size, 0, 0);
        if (!(sv_isobject(type) && sv_derived_from(type, "Affix::Type::Base")))
            croak("Given type for '%s' is not a subclass of Affix::Type::Base",
                  SvPV_nolen(type));
        size_t offset = 0;
        size_t type_sizeof = _sizeof(aTHX_ type);
    } break;
    case 2: {
        array_length = SvUV(*av_fetch(type_size, 1, 0));
        if (array_length < 1) croak("Given size %zd is not a positive integer", array_length);
        type = *av_fetch(type_size, 0, 0);
        if (!(sv_isobject(type) && sv_derived_from(type, "Affix::Type::Base")))
            croak("Given type for '%s' is not a subclass of Affix::Type::Base",
                  SvPV_nolen(type));
        size_t offset = 0;
        size_t type_sizeof = _sizeof(aTHX_ type);
        for (int i = 0; i < array_length; ++i) {
            array_sizeof += type_sizeof;
            array_sizeof +=
                packed ? 0
                       : padding_needed_for(array_sizeof, AFFIX_ALIGNBYTES > type_sizeof
                                                              ? type_sizeof
                                                              : AFFIX_ALIGNBYTES);
            offset = array_sizeof;
        }
        size = newSVuv(array_length);
    } break;
    default:
        croak("Expected a single type and array length: "
              "ArrayRef[Int, 5]");
    }
    hv_stores(RETVAL_HV, "sizeof", newSVuv(array_sizeof));
    hv_stores(RETVAL_HV, "size", size);
    hv_stores(RETVAL_HV, "name", newSV(0));
    hv_stores(RETVAL_HV, "packed", sv_2mortal(boolSV(packed)));
    hv_stores(RETVAL_HV, "type", newSVsv(type));
} break;
case DC_SIGCHAR_CODE: {
    AV *fields = newAV_mortal();

t/50_affix_pointers.t  view on Meta::CPAN

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
    is $ptr, 1000, '$ptr was changed to 1000';
    diag __LINE__;
};
diag __LINE__;
subtest 'Dyn::Call::Pointer with a double' => sub {
    diag __LINE__;
    my $ptr = calloc( 1, 16 );
    {
        diag __LINE__;
        my $data = pack 'd', 100.04;
        memcpy( $ptr, $data, length $data );
    }
    is dbl_ptr($ptr), 'one hundred and change', 'dbl_ptr($ptr) where $ptr == malloc(...)';
    $ptr->dump(16);
    diag __LINE__;
    my $raw = $ptr->raw(16);
    is unpack( 'd', $raw ), 10000, '$ptr was changed to 10000';
    free $ptr;
    diag __LINE__;
};
diag __LINE__;
subtest 'ref Dyn::Call::Pointer with a double (should croak)' => sub {
    diag __LINE__;
    my $ptr = calloc( 1, 16 );
    {
        diag __LINE__;
        my $data = pack 'd', 9;
        memcpy( $ptr, $data, length $data );
    }
    diag __LINE__;
    is dbl_ptr($ptr), 'nine', 'dbl_ptr($ptr) where $ptr == malloc(...)';
    is unpack( 'd', $ptr->raw(16) ),
        ( $Config{usequadmath} ? 9876.54299999999966530594974756241 :
            $Config{uselongdouble} ? 9876.54299999999967 :
            9876.543 ), '$ptr is still 9';
    diag __LINE__;
    DumpHex( $ptr, 16 );
    diag __LINE__;

t/50_affix_pointers.t  view on Meta::CPAN

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
            diag __LINE__;
            50.25;
        }
        ),
        -1, 'making call with an undef pointer passes a NULL';
}
diag __LINE__;
{
    my $data = pack 'd', 590343.12351;    # Test pumping raw, packed data into memory
    diag __LINE__;
    my $ptr = malloc length($data);
    diag __LINE__;
    memmove $ptr, $data, length $data;
    diag __LINE__;
    diag 'allocated ' . length($data) . ' bytes';
    diag __LINE__;
    is pointer_test(
        $ptr,
        [ 1 .. 5 ],
        5,
        sub {
            diag __LINE__;
            pass('our coderef was called');
            is_deeply \@_, [ 4, 8 ], '... and given correct arguments';
            50.25;

t/51_affix_sizeof_offsetof.t  view on Meta::CPAN

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
        is sizeof( massive() ), wrap( $lib, 's_massive', [], Size_t )->(), 'sizeof(massive)';
    }
 
    #diag Dumper $struct7;
    is sizeof($struct7), wrap( $lib, 's_struct7', [], Size_t )->(), 'sizeof(struct7)';
    is sizeof($struct8), wrap( $lib, 's_struct8', [], Size_t )->(), 'sizeof(struct8)';
};
subtest 'arrays' => sub {
 
    #die sizeof( Struct [ d => Double, c => ArrayRef [ Int, 4 ] ]);
    for my $length ( 1 .. 3 ) {
        my $array1 = ArrayRef [ Struct [ d => Double, c => ArrayRef [ Int, 4 ] ], $length ];
 
        #diag Dumper $array1;
        is sizeof($array1), wrap( $lib, 's_array1', [Int], Size_t )->($length),
            'sizeof(array1) [' . $length . ']';
    }
};
subtest 'unions' => sub {
    my $union1 = Union [ i => Int, d => Float ];
    my $union2 = Union [ i => Int, s => $struct1, d => Float ];
    my $union3 = Union [ i => Int, s => $struct3, d => Float ];
    my $union4 = Union [ i => Int, s => ArrayRef [ $struct1, 5 ], d => Float ];
    is sizeof($union1), wrap( $lib, 's_union1', [], Size_t )->(), 'sizeof(union1)';
    is sizeof($union2), wrap( $lib, 's_union2', [], Size_t )->(), 'sizeof(union2)';
SKIP: {

t/src/51_affix_sizeof_offsetof.c  view on Meta::CPAN

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
} massive;
DLLEXPORT size_t s_massive() {
    return sizeof(massive);
}
 
//
typedef struct {
    double d;
    int c[4];
} array_struct;
DLLEXPORT size_t s_array1(int length) {
    return sizeof(array_struct[length]);
}
 
//
typedef union
{
    int i;
    float d;
} union1;
 
typedef union



( run in 1.282 second using v1.01-cache-2.11-cpan-a9ef4e587e4 )