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