xref: /third_party/openssl/util/mkdef.pl (revision e1051a39)
1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ci# Generate a linker version script suitable for the given platform
10e1051a39Sopenharmony_ci# from a given ordinals file.
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ciuse strict;
13e1051a39Sopenharmony_ciuse warnings;
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ciuse Getopt::Long;
16e1051a39Sopenharmony_ciuse FindBin;
17e1051a39Sopenharmony_ciuse lib "$FindBin::Bin/perl";
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ciuse OpenSSL::Ordinals;
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ciuse lib '.';
22e1051a39Sopenharmony_ciuse configdata;
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ciuse File::Spec::Functions;
25e1051a39Sopenharmony_ciuse lib catdir($config{sourcedir}, 'Configurations');
26e1051a39Sopenharmony_ciuse platform;
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_cimy $name = undef;               # internal library/module name
29e1051a39Sopenharmony_cimy $ordinals_file = undef;      # the ordinals file to use
30e1051a39Sopenharmony_cimy $version = undef;            # the version to use for the library
31e1051a39Sopenharmony_cimy $OS = undef;                 # the operating system family
32e1051a39Sopenharmony_cimy $type = 'lib';               # either lib or dso
33e1051a39Sopenharmony_cimy $verbose = 0;
34e1051a39Sopenharmony_cimy $ctest = 0;
35e1051a39Sopenharmony_cimy $debug = 0;
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci# For VMS, some modules may have case insensitive names
38e1051a39Sopenharmony_cimy $case_insensitive = 0;
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ciGetOptions('name=s'     => \$name,
41e1051a39Sopenharmony_ci           'ordinals=s' => \$ordinals_file,
42e1051a39Sopenharmony_ci           'version=s'  => \$version,
43e1051a39Sopenharmony_ci           'OS=s'       => \$OS,
44e1051a39Sopenharmony_ci           'type=s'     => \$type,
45e1051a39Sopenharmony_ci           'ctest'      => \$ctest,
46e1051a39Sopenharmony_ci           'verbose'    => \$verbose,
47e1051a39Sopenharmony_ci           # For VMS
48e1051a39Sopenharmony_ci           'case-insensitive' => \$case_insensitive)
49e1051a39Sopenharmony_ci    or die "Error in command line arguments\n";
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_cidie "Please supply arguments\n"
52e1051a39Sopenharmony_ci    unless $name && $ordinals_file && $OS;
53e1051a39Sopenharmony_cidie "--type argument must be equal to 'lib' or 'dso'"
54e1051a39Sopenharmony_ci    if $type ne 'lib' && $type ne 'dso';
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci# When building a "variant" shared library, with a custom SONAME, also customize
57e1051a39Sopenharmony_ci# all the symbol versions.  This produces a shared object that can coexist
58e1051a39Sopenharmony_ci# without conflict in the same address space as a default build, or an object
59e1051a39Sopenharmony_ci# with a different variant tag.
60e1051a39Sopenharmony_ci#
61e1051a39Sopenharmony_ci# For example, with a target definition that includes:
62e1051a39Sopenharmony_ci#
63e1051a39Sopenharmony_ci#         shlib_variant => "-opt",
64e1051a39Sopenharmony_ci#
65e1051a39Sopenharmony_ci# we build the following objects:
66e1051a39Sopenharmony_ci#
67e1051a39Sopenharmony_ci# $ perl -le '
68e1051a39Sopenharmony_ci#     for (@ARGV) {
69e1051a39Sopenharmony_ci#         if ($l = readlink) {
70e1051a39Sopenharmony_ci#             printf "%s -> %s\n", $_, $l
71e1051a39Sopenharmony_ci#         } else {
72e1051a39Sopenharmony_ci#             print
73e1051a39Sopenharmony_ci#         }
74e1051a39Sopenharmony_ci#     }' *.so*
75e1051a39Sopenharmony_ci# libcrypto-opt.so.1.1
76e1051a39Sopenharmony_ci# libcrypto.so -> libcrypto-opt.so.1.1
77e1051a39Sopenharmony_ci# libssl-opt.so.1.1
78e1051a39Sopenharmony_ci# libssl.so -> libssl-opt.so.1.1
79e1051a39Sopenharmony_ci#
80e1051a39Sopenharmony_ci# whose SONAMEs and dependencies are:
81e1051a39Sopenharmony_ci#
82e1051a39Sopenharmony_ci# $ for l in *.so; do
83e1051a39Sopenharmony_ci#     echo $l
84e1051a39Sopenharmony_ci#     readelf -d $l | egrep 'SONAME|NEEDED.*(ssl|crypto)'
85e1051a39Sopenharmony_ci#   done
86e1051a39Sopenharmony_ci# libcrypto.so
87e1051a39Sopenharmony_ci#  0x000000000000000e (SONAME)             Library soname: [libcrypto-opt.so.1.1]
88e1051a39Sopenharmony_ci# libssl.so
89e1051a39Sopenharmony_ci#  0x0000000000000001 (NEEDED)             Shared library: [libcrypto-opt.so.1.1]
90e1051a39Sopenharmony_ci#  0x000000000000000e (SONAME)             Library soname: [libssl-opt.so.1.1]
91e1051a39Sopenharmony_ci#
92e1051a39Sopenharmony_ci# We case-fold the variant tag to upper case and replace all non-alnum
93e1051a39Sopenharmony_ci# characters with "_".  This yields the following symbol versions:
94e1051a39Sopenharmony_ci#
95e1051a39Sopenharmony_ci# $ nm libcrypto.so | grep -w A
96e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0
97e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0a
98e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0c
99e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0d
100e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0f
101e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0g
102e1051a39Sopenharmony_ci# $ nm libssl.so | grep -w A
103e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0
104e1051a39Sopenharmony_ci# 0000000000000000 A OPENSSL_OPT_1_1_0d
105e1051a39Sopenharmony_ci#
106e1051a39Sopenharmony_ci(my $SO_VARIANT = uc($target{"shlib_variant"} // '')) =~ s/\W/_/g;
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_cimy $libname = $type eq 'lib' ? platform->sharedname($name) : platform->dsoname($name);
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_cimy %OS_data = (
111e1051a39Sopenharmony_ci    solaris     => { writer     => \&writer_linux,
112e1051a39Sopenharmony_ci                     sort       => sorter_linux(),
113e1051a39Sopenharmony_ci                     platforms  => { UNIX                       => 1 } },
114e1051a39Sopenharmony_ci    "solaris-gcc" => 'solaris', # alias
115e1051a39Sopenharmony_ci    linux       => 'solaris',   # alias
116e1051a39Sopenharmony_ci    "bsd-gcc"   => 'solaris',   # alias
117e1051a39Sopenharmony_ci    aix         => { writer     => \&writer_aix,
118e1051a39Sopenharmony_ci                     sort       => sorter_unix(),
119e1051a39Sopenharmony_ci                     platforms  => { UNIX                       => 1 } },
120e1051a39Sopenharmony_ci    VMS         => { writer     => \&writer_VMS,
121e1051a39Sopenharmony_ci                     sort       => OpenSSL::Ordinals::by_number(),
122e1051a39Sopenharmony_ci                     platforms  => { VMS                        => 1 } },
123e1051a39Sopenharmony_ci    vms         => 'VMS',       # alias
124e1051a39Sopenharmony_ci    WINDOWS     => { writer     => \&writer_windows,
125e1051a39Sopenharmony_ci                     sort       => OpenSSL::Ordinals::by_name(),
126e1051a39Sopenharmony_ci                     platforms  => { WIN32                      => 1,
127e1051a39Sopenharmony_ci                                     _WIN32                     => 1 } },
128e1051a39Sopenharmony_ci    windows     => 'WINDOWS',   # alias
129e1051a39Sopenharmony_ci    WIN32       => 'WINDOWS',   # alias
130e1051a39Sopenharmony_ci    win32       => 'WIN32',     # alias
131e1051a39Sopenharmony_ci    32          => 'WIN32',     # alias
132e1051a39Sopenharmony_ci    NT          => 'WIN32',     # alias
133e1051a39Sopenharmony_ci    nt          => 'WIN32',     # alias
134e1051a39Sopenharmony_ci    mingw       => 'WINDOWS',   # alias
135e1051a39Sopenharmony_ci    nonstop     => { writer     => \&writer_nonstop,
136e1051a39Sopenharmony_ci                     sort       => OpenSSL::Ordinals::by_name(),
137e1051a39Sopenharmony_ci                     platforms  => { TANDEM                     => 1 } },
138e1051a39Sopenharmony_ci   );
139e1051a39Sopenharmony_ci
140e1051a39Sopenharmony_cido {
141e1051a39Sopenharmony_ci    die "Unknown operating system family $OS\n"
142e1051a39Sopenharmony_ci        unless exists $OS_data{$OS};
143e1051a39Sopenharmony_ci    $OS = $OS_data{$OS};
144e1051a39Sopenharmony_ci} while(ref($OS) eq '');
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_cimy %disabled_uc = map { my $x = uc $_; $x =~ s|-|_|g; $x => 1 } keys %disabled;
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_cimy %ordinal_opts = ();
149e1051a39Sopenharmony_ci$ordinal_opts{sort} = $OS->{sort} if $OS->{sort};
150e1051a39Sopenharmony_ci$ordinal_opts{filter} =
151e1051a39Sopenharmony_ci    sub {
152e1051a39Sopenharmony_ci        my $item = shift;
153e1051a39Sopenharmony_ci        return
154e1051a39Sopenharmony_ci            $item->exists()
155e1051a39Sopenharmony_ci            && platform_filter($item)
156e1051a39Sopenharmony_ci            && feature_filter($item);
157e1051a39Sopenharmony_ci    };
158e1051a39Sopenharmony_cimy $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file);
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_cimy $writer = $OS->{writer};
161e1051a39Sopenharmony_ci$writer = \&writer_ctest if $ctest;
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ci$writer->($ordinals->items(%ordinal_opts));
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ciexit 0;
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_cisub platform_filter {
168e1051a39Sopenharmony_ci    my $item = shift;
169e1051a39Sopenharmony_ci    my %platforms = ( $item->platforms() );
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_ci    # True if no platforms are defined
172e1051a39Sopenharmony_ci    return 1 if scalar keys %platforms == 0;
173e1051a39Sopenharmony_ci
174e1051a39Sopenharmony_ci    # For any item platform tag, return the equivalence with the
175e1051a39Sopenharmony_ci    # current platform settings if it exists there, return 0 otherwise
176e1051a39Sopenharmony_ci    # if the item platform tag is true
177e1051a39Sopenharmony_ci    for (keys %platforms) {
178e1051a39Sopenharmony_ci        if (exists $OS->{platforms}->{$_}) {
179e1051a39Sopenharmony_ci            return $platforms{$_} == $OS->{platforms}->{$_};
180e1051a39Sopenharmony_ci        }
181e1051a39Sopenharmony_ci        if ($platforms{$_}) {
182e1051a39Sopenharmony_ci            return 0;
183e1051a39Sopenharmony_ci        }
184e1051a39Sopenharmony_ci    }
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    # Found no match?  Then it's a go
187e1051a39Sopenharmony_ci    return 1;
188e1051a39Sopenharmony_ci}
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_cisub feature_filter {
191e1051a39Sopenharmony_ci    my $item = shift;
192e1051a39Sopenharmony_ci    my @features = ( $item->features() );
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci    # True if no features are defined
195e1051a39Sopenharmony_ci    return 1 if scalar @features == 0;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    my $verdict = ! grep { $disabled_uc{$_} } @features;
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci    if ($disabled{deprecated}) {
200e1051a39Sopenharmony_ci        foreach (@features) {
201e1051a39Sopenharmony_ci            next unless /^DEPRECATEDIN_(\d+)_(\d+)(?:_(\d+))?$/;
202e1051a39Sopenharmony_ci            my $symdep = $1 * 10000 + $2 * 100 + ($3 // 0);
203e1051a39Sopenharmony_ci            $verdict = 0 if $config{api} >= $symdep;
204e1051a39Sopenharmony_ci            print STDERR "DEBUG: \$symdep = $symdep, \$verdict = $verdict\n"
205e1051a39Sopenharmony_ci                if $debug && $1 == 0;
206e1051a39Sopenharmony_ci        }
207e1051a39Sopenharmony_ci    }
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_ci    return $verdict;
210e1051a39Sopenharmony_ci}
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_cisub sorter_unix {
213e1051a39Sopenharmony_ci    my $by_name = OpenSSL::Ordinals::by_name();
214e1051a39Sopenharmony_ci    my %weight = (
215e1051a39Sopenharmony_ci        'FUNCTION'      => 1,
216e1051a39Sopenharmony_ci        'VARIABLE'      => 2
217e1051a39Sopenharmony_ci       );
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_ci    return sub {
220e1051a39Sopenharmony_ci        my $item1 = shift;
221e1051a39Sopenharmony_ci        my $item2 = shift;
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ci        my $verdict = $weight{$item1->type()} <=> $weight{$item2->type()};
224e1051a39Sopenharmony_ci        if ($verdict == 0) {
225e1051a39Sopenharmony_ci            $verdict = $by_name->($item1, $item2);
226e1051a39Sopenharmony_ci        }
227e1051a39Sopenharmony_ci        return $verdict;
228e1051a39Sopenharmony_ci    };
229e1051a39Sopenharmony_ci}
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_cisub sorter_linux {
232e1051a39Sopenharmony_ci    my $by_version = OpenSSL::Ordinals::by_version();
233e1051a39Sopenharmony_ci    my $by_unix = sorter_unix();
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ci    return sub {
236e1051a39Sopenharmony_ci        my $item1 = shift;
237e1051a39Sopenharmony_ci        my $item2 = shift;
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ci        my $verdict = $by_version->($item1, $item2);
240e1051a39Sopenharmony_ci        if ($verdict == 0) {
241e1051a39Sopenharmony_ci            $verdict = $by_unix->($item1, $item2);
242e1051a39Sopenharmony_ci        }
243e1051a39Sopenharmony_ci        return $verdict;
244e1051a39Sopenharmony_ci    };
245e1051a39Sopenharmony_ci}
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_cisub writer_linux {
248e1051a39Sopenharmony_ci    my $thisversion = '';
249e1051a39Sopenharmony_ci    my $currversion_s = '';
250e1051a39Sopenharmony_ci    my $prevversion_s = '';
251e1051a39Sopenharmony_ci    my $indent = 0;
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ci    for (@_) {
254e1051a39Sopenharmony_ci        if ($thisversion && $_->version() ne $thisversion) {
255e1051a39Sopenharmony_ci            die "$ordinals_file: It doesn't make sense to have both versioned ",
256e1051a39Sopenharmony_ci                "and unversioned symbols"
257e1051a39Sopenharmony_ci                if $thisversion eq '*';
258e1051a39Sopenharmony_ci            print <<"_____";
259e1051a39Sopenharmony_ci}${prevversion_s};
260e1051a39Sopenharmony_ci_____
261e1051a39Sopenharmony_ci            $prevversion_s = " OPENSSL${SO_VARIANT}_$thisversion";
262e1051a39Sopenharmony_ci            $thisversion = '';  # Trigger start of next section
263e1051a39Sopenharmony_ci        }
264e1051a39Sopenharmony_ci        unless ($thisversion) {
265e1051a39Sopenharmony_ci            $indent = 0;
266e1051a39Sopenharmony_ci            $thisversion = $_->version();
267e1051a39Sopenharmony_ci            $currversion_s = '';
268e1051a39Sopenharmony_ci            $currversion_s = "OPENSSL${SO_VARIANT}_$thisversion "
269e1051a39Sopenharmony_ci                if $thisversion ne '*';
270e1051a39Sopenharmony_ci            print <<"_____";
271e1051a39Sopenharmony_ci${currversion_s}{
272e1051a39Sopenharmony_ci    global:
273e1051a39Sopenharmony_ci_____
274e1051a39Sopenharmony_ci        }
275e1051a39Sopenharmony_ci        print '        ', $_->name(), ";\n";
276e1051a39Sopenharmony_ci    }
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ci    print <<"_____";
279e1051a39Sopenharmony_ci    local: *;
280e1051a39Sopenharmony_ci}${prevversion_s};
281e1051a39Sopenharmony_ci_____
282e1051a39Sopenharmony_ci}
283e1051a39Sopenharmony_ci
284e1051a39Sopenharmony_cisub writer_aix {
285e1051a39Sopenharmony_ci    for (@_) {
286e1051a39Sopenharmony_ci        print $_->name(),"\n";
287e1051a39Sopenharmony_ci    }
288e1051a39Sopenharmony_ci}
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_cisub writer_nonstop {
291e1051a39Sopenharmony_ci    for (@_) {
292e1051a39Sopenharmony_ci        print "-export ",$_->name(),"\n";
293e1051a39Sopenharmony_ci    }
294e1051a39Sopenharmony_ci}
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_cisub writer_windows {
297e1051a39Sopenharmony_ci    print <<"_____";
298e1051a39Sopenharmony_ci;
299e1051a39Sopenharmony_ci; Definition file for the DLL version of the $libname library from OpenSSL
300e1051a39Sopenharmony_ci;
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ciLIBRARY         "$libname"
303e1051a39Sopenharmony_ci
304e1051a39Sopenharmony_ciEXPORTS
305e1051a39Sopenharmony_ci_____
306e1051a39Sopenharmony_ci    for (@_) {
307e1051a39Sopenharmony_ci        print "    ",$_->name();
308e1051a39Sopenharmony_ci        if (platform->can('export2internal')) {
309e1051a39Sopenharmony_ci            print "=". platform->export2internal($_->name());
310e1051a39Sopenharmony_ci        }
311e1051a39Sopenharmony_ci        print "\n";
312e1051a39Sopenharmony_ci    }
313e1051a39Sopenharmony_ci}
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_cisub collect_VMS_mixedcase {
316e1051a39Sopenharmony_ci    return [ 'SPARE', 'SPARE' ] unless @_;
317e1051a39Sopenharmony_ci
318e1051a39Sopenharmony_ci    my $s = shift;
319e1051a39Sopenharmony_ci    my $s_uc = uc($s);
320e1051a39Sopenharmony_ci    my $type = shift;
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_ci    return [ "$s=$type", 'SPARE' ] if $s_uc eq $s;
323e1051a39Sopenharmony_ci    return [ "$s_uc/$s=$type", "$s=$type" ];
324e1051a39Sopenharmony_ci}
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_cisub collect_VMS_uppercase {
327e1051a39Sopenharmony_ci    return [ 'SPARE' ] unless @_;
328e1051a39Sopenharmony_ci
329e1051a39Sopenharmony_ci    my $s = shift;
330e1051a39Sopenharmony_ci    my $s_uc = uc($s);
331e1051a39Sopenharmony_ci    my $type = shift;
332e1051a39Sopenharmony_ci
333e1051a39Sopenharmony_ci    return [ "$s_uc=$type" ];
334e1051a39Sopenharmony_ci}
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_cisub writer_VMS {
337e1051a39Sopenharmony_ci    my @slot_collection = ();
338e1051a39Sopenharmony_ci    my $collector =
339e1051a39Sopenharmony_ci        $case_insensitive ? \&collect_VMS_uppercase : \&collect_VMS_mixedcase;
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ci    my $last_num = 0;
342e1051a39Sopenharmony_ci    foreach (@_) {
343e1051a39Sopenharmony_ci        my $this_num = $_->number();
344e1051a39Sopenharmony_ci        $this_num = $last_num + 1 if $this_num =~ m|^\?|;
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_ci        while (++$last_num < $this_num) {
347e1051a39Sopenharmony_ci            push @slot_collection, $collector->(); # Just occupy a slot
348e1051a39Sopenharmony_ci        }
349e1051a39Sopenharmony_ci        my $type = {
350e1051a39Sopenharmony_ci            FUNCTION    => 'PROCEDURE',
351e1051a39Sopenharmony_ci            VARIABLE    => 'DATA'
352e1051a39Sopenharmony_ci           } -> {$_->type()};
353e1051a39Sopenharmony_ci        push @slot_collection, $collector->($_->name(), $type);
354e1051a39Sopenharmony_ci    }
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ci    print <<"_____" if defined $version;
357e1051a39Sopenharmony_ciIDENTIFICATION=$version
358e1051a39Sopenharmony_ci_____
359e1051a39Sopenharmony_ci    print <<"_____" unless $case_insensitive;
360e1051a39Sopenharmony_ciCASE_SENSITIVE=YES
361e1051a39Sopenharmony_ci_____
362e1051a39Sopenharmony_ci    print <<"_____";
363e1051a39Sopenharmony_ciSYMBOL_VECTOR=(-
364e1051a39Sopenharmony_ci_____
365e1051a39Sopenharmony_ci    # It's uncertain how long aggregated lines the linker can handle,
366e1051a39Sopenharmony_ci    # but it has been observed that at least 1024 characters is ok.
367e1051a39Sopenharmony_ci    # Either way, this means that we need to keep track of the total
368e1051a39Sopenharmony_ci    # line length of each "SYMBOL_VECTOR" statement.  Fortunately, we
369e1051a39Sopenharmony_ci    # can have more than one of those...
370e1051a39Sopenharmony_ci    my $symvtextcount = 16;     # The length of "SYMBOL_VECTOR=("
371e1051a39Sopenharmony_ci    while (@slot_collection) {
372e1051a39Sopenharmony_ci        my $set = shift @slot_collection;
373e1051a39Sopenharmony_ci        my $settextlength = 0;
374e1051a39Sopenharmony_ci        foreach (@$set) {
375e1051a39Sopenharmony_ci            $settextlength +=
376e1051a39Sopenharmony_ci                + 3             # two space indentation and comma
377e1051a39Sopenharmony_ci                + length($_)
378e1051a39Sopenharmony_ci                + 1             # postdent
379e1051a39Sopenharmony_ci                ;
380e1051a39Sopenharmony_ci        }
381e1051a39Sopenharmony_ci        $settextlength--;       # only one space indentation on the first one
382e1051a39Sopenharmony_ci        my $firstcomma = ',';
383e1051a39Sopenharmony_ci
384e1051a39Sopenharmony_ci        if ($symvtextcount + $settextlength > 1024) {
385e1051a39Sopenharmony_ci            print <<"_____";
386e1051a39Sopenharmony_ci)
387e1051a39Sopenharmony_ciSYMBOL_VECTOR=(-
388e1051a39Sopenharmony_ci_____
389e1051a39Sopenharmony_ci            $symvtextcount = 16; # The length of "SYMBOL_VECTOR=("
390e1051a39Sopenharmony_ci        }
391e1051a39Sopenharmony_ci        if ($symvtextcount == 16) {
392e1051a39Sopenharmony_ci            $firstcomma = '';
393e1051a39Sopenharmony_ci        }
394e1051a39Sopenharmony_ci
395e1051a39Sopenharmony_ci        my $indent = ' '.$firstcomma;
396e1051a39Sopenharmony_ci        foreach (@$set) {
397e1051a39Sopenharmony_ci            print <<"_____";
398e1051a39Sopenharmony_ci$indent$_ -
399e1051a39Sopenharmony_ci_____
400e1051a39Sopenharmony_ci            $symvtextcount += length($indent) + length($_) + 1;
401e1051a39Sopenharmony_ci            $indent = '  ,';
402e1051a39Sopenharmony_ci        }
403e1051a39Sopenharmony_ci    }
404e1051a39Sopenharmony_ci    print <<"_____";
405e1051a39Sopenharmony_ci)
406e1051a39Sopenharmony_ci_____
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci    if (defined $version) {
409e1051a39Sopenharmony_ci        $version =~ /^(\d+)\.(\d+)\.(\d+)/;
410e1051a39Sopenharmony_ci        my $libvmajor = $1;
411e1051a39Sopenharmony_ci        my $libvminor = $2 * 100 + $3;
412e1051a39Sopenharmony_ci        print <<"_____";
413e1051a39Sopenharmony_ciGSMATCH=LEQUAL,$libvmajor,$libvminor
414e1051a39Sopenharmony_ci_____
415e1051a39Sopenharmony_ci    }
416e1051a39Sopenharmony_ci}
417e1051a39Sopenharmony_ci
418e1051a39Sopenharmony_cisub writer_ctest {
419e1051a39Sopenharmony_ci    print <<'_____';
420e1051a39Sopenharmony_ci/*
421e1051a39Sopenharmony_ci * Test file to check all DEF file symbols are present by trying
422e1051a39Sopenharmony_ci * to link to all of them. This is *not* intended to be run!
423e1051a39Sopenharmony_ci */
424e1051a39Sopenharmony_ci
425e1051a39Sopenharmony_ciint main()
426e1051a39Sopenharmony_ci{
427e1051a39Sopenharmony_ci_____
428e1051a39Sopenharmony_ci
429e1051a39Sopenharmony_ci    my $last_num = 0;
430e1051a39Sopenharmony_ci    for (@_) {
431e1051a39Sopenharmony_ci        my $this_num = $_->number();
432e1051a39Sopenharmony_ci        $this_num = $last_num + 1 if $this_num =~ m|^\?|;
433e1051a39Sopenharmony_ci
434e1051a39Sopenharmony_ci        if ($_->type() eq 'VARIABLE') {
435e1051a39Sopenharmony_ci            print "\textern int ", $_->name(), '; /* type unknown */ /* ',
436e1051a39Sopenharmony_ci                  $this_num, ' ', $_->version(), " */\n";
437e1051a39Sopenharmony_ci        } else {
438e1051a39Sopenharmony_ci            print "\textern int ", $_->name(), '(); /* type unknown */ /* ',
439e1051a39Sopenharmony_ci                  $this_num, ' ', $_->version(), " */\n";
440e1051a39Sopenharmony_ci        }
441e1051a39Sopenharmony_ci
442e1051a39Sopenharmony_ci        $last_num = $this_num;
443e1051a39Sopenharmony_ci    }
444e1051a39Sopenharmony_ci    print <<'_____';
445e1051a39Sopenharmony_ci}
446e1051a39Sopenharmony_ci_____
447e1051a39Sopenharmony_ci}
448