1################################################################################
2#
3# PROGRAM: arch.pl
4#
5################################################################################
6#
7# DESCRIPTION: Generate header file for architecture specific definitions
8#
9################################################################################
10#
11# Copyright (c) 2002-2020 Marcus Holland-Moritz. All rights reserved.
12# This program is free software; you can redistribute it and/or modify
13# it under the same terms as Perl itself.
14#
15################################################################################
16
17use Config;
18
19$file = @ARGV ? shift : 'ctlib/arch.h';
20open OUT, ">$file" or die "$file: $!\n";
21
22%cfg = %Config;  # because we modify some values in %cfg
23
24%use = (
25  '64BIT'      => 1,
26  'LONGLONG'   => 1,
27  'LONGDOUBLE' => 1,
28);
29
30if( $Config{osname} eq 'hpux' and $Config{cc} eq 'cc' and
31    $Config{osvers} =~ /(\d+)\.(\d+)/ and $1 < 11 ) {
32  # At least some versions of HP's cc compiler have a broken
33  # preprocessor/compiler implementation of 64-bit data types.
34  $use{'64BIT'}    = 0;
35  $use{'LONGLONG'} = 0;
36}
37
38for( keys %use ) {
39  exists $ENV{"CBC_USE$_"} and $use{$_} = $ENV{"CBC_USE$_"};
40}
41
42# <HACK> required to support perl < 5.6.0
43
44unless( exists $cfg{i8type} ) {
45  $b8 = 'char';
46
47  for( qw( int short long ) ) {
48    if( not defined $b16 and $cfg{"${_}size"} == 2 ) { $b16 = $_ }
49    if( not defined $b32 and $cfg{"${_}size"} == 4 ) { $b32 = $_ }
50  }
51
52  defined $b16 and defined $b32 or die "cannot determine integer sizes";
53
54  $cfg{i8type}  = "signed $b8";
55  $cfg{u8type}  = "unsigned $b8";
56  $cfg{i16type} = "signed $b16";
57  $cfg{u16type} = "unsigned $b16";
58  $cfg{i32type} = "signed $b32";
59  $cfg{u32type} = "unsigned $b32";
60}
61
62# </HACK>
63
64# make the i_8 explicitly signed
65# (i8type was plain 'char' on an IPAQ system where 'char' was unsigned)
66if( $cfg{i8type} eq 'char' ) {
67  $cfg{i8type} = 'signed char';
68}
69
70sub is_big_endian ()
71{
72  my $byteorder = $cfg{byteorder}
73               || unpack( "a*", pack "L", 0x34333231 );
74
75  die "Native byte order ($byteorder) not supported!\n"
76      if   $byteorder ne '1234'     and $byteorder ne '4321'
77       and $byteorder ne '12345678' and $byteorder ne '87654321';
78
79  $byteorder eq '4321' or $byteorder eq '87654321';
80}
81
82sub config ($) {
83  local $_ = shift;
84  s/\$\{([^}]+)\}/$cfg{$1}/g;
85  print OUT;
86}
87
88$long_double = $use{LONGDOUBLE} && $cfg{d_longdbl} eq 'define' ? 1 : 0;
89print "DISABLED long double support\n" if $use{LONGDOUBLE} == 0;
90
91$long_long = $use{LONGLONG} && $cfg{d_longlong} eq 'define' ? 1 : 0;
92print "DISABLED long long support\n" if $use{LONGLONG} == 0;
93
94config <<ENDCFG;
95#ifndef _CTLIB_ARCH_H
96#define _CTLIB_ARCH_H
97
98#define ARCH_HAVE_LONG_DOUBLE        $long_double
99#define ARCH_HAVE_LONG_LONG          $long_long
100ENDCFG
101
102if( $use{'64BIT'} && $cfg{d_quad} eq 'define' ) {
103config <<'ENDCFG';
104#define ARCH_NATIVE_64_BIT_INTEGER   1
105
106/* 64-bit integer data types */
107typedef ${i64type} i_64;
108typedef ${u64type} u_64;
109
110ENDCFG
111}
112elsif( $use{'64BIT'} && $cfg{d_longlong} eq 'define' and $cfg{longlongsize} == 8 ) {
113config <<'ENDCFG';
114#define ARCH_NATIVE_64_BIT_INTEGER   1
115
116/* 64-bit integer data types */
117typedef signed long long i_64;
118typedef unsigned long long u_64;
119
120ENDCFG
121}
122else {
123  print "DISABLED 64-bit support\n" if $use{'64BIT'} == 0;
124config <<'ENDCFG';
125#define ARCH_NATIVE_64_BIT_INTEGER   0
126
127/* no native 64-bit support */
128typedef struct {
129  ${u32type} h;
130  ${u32type} l;
131} u_64;
132
133typedef struct {
134  ${i32type} h;
135  ${u32type} l;
136} i_64;
137
138ENDCFG
139}
140
141$byteorder = is_big_endian ? 'BIG' : 'LITTLE';
142
143config <<"ENDCFG";
144#define ARCH_BYTEORDER_BIG_ENDIAN    1
145#define ARCH_BYTEORDER_LITTLE_ENDIAN 2
146#define ARCH_NATIVE_BYTEORDER        ARCH_BYTEORDER_${byteorder}_ENDIAN
147
148ENDCFG
149
150config <<'ENDCFG';
151/* 32-bit integer data types */
152typedef ${i32type} i_32;
153typedef ${u32type} u_32;
154
155/* 16-bit integer data types */
156typedef ${i16type} i_16;
157typedef ${u16type} u_16;
158
159/* 8-bit integer data types */
160typedef ${i8type} i_8;
161typedef ${u8type} u_8;
162
163ENDCFG
164
165config <<'ENDCFG';
166#endif
167ENDCFG
168
169close OUT;
170