4 #//===----------------------------------------------------------------------===//
6 #// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
7 #// See https://llvm.org/LICENSE.txt for license information.
8 #// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10 #//===----------------------------------------------------------------------===//
14 use strict
; # Restrict unsafe constructs.
15 use warnings
; # Enable all warnings.
18 use lib
"$FindBin::Bin/lib";
22 our $VERSION = "0.004";
28 sub parse_input
($\
%) {
30 my ( $input, $defs ) = @_;
31 my @bulk = read_file
( $input );
39 my ( $msg, $l, $line ) = @_;
41 "Error parsing file \"$input\" line $l:\n" .
43 ( $msg ?
$msg . "\n" : () )
47 my $n = 0; # Line number.
48 foreach my $line ( @bulk ) {
51 } elsif ( $line =~ m{^\s*(?:#|\n)} ) {
52 # Empty line or comment. Skip it.
53 } elsif ( $line =~ m{^\s*%} ) {
56 } elsif ( $line =~ m{^\s*%\s*if(n)?def\s+([A-Za-z0-9_]+)\s*(?:#|\n)} ) {
57 my ( $negation, $name ) = ( $1, $2 );
58 my $dir = { n
=> $n, line
=> $line, name
=> $name, value
=> $value };
60 $value = ( $value and ( $negation xor $defs->{ $name } ) );
61 } elsif ( $line =~ m{^\s*%\s*endif\s*(?:#|\n)} ) {
63 $error->( "Orphan %endif directive.", $n, $line );
65 my $dir = pop( @dirs );
66 $value = $dir->{ value
};
68 $error->( "Bad directive.", $n, $line );
70 } elsif ( $line =~ m{^\s*(-)?\s*([A-Za-z0-9_]+)(?:\s+(\d+|DATA))?\s*(?:#|\n)} ) {
71 my ( $obsolete, $entry, $ordinal ) = ( $1, $2, $3 );
73 if ( exists( $entries{ $entry } ) ) {
74 $error->( "Entry \"$entry\" has already been specified.", $n, $line );
76 $entries{ $entry } = { ordinal
=> $ordinal, obsolete
=> defined( $obsolete ) };
77 if ( defined( $ordinal ) and $ordinal ne "DATA" ) {
78 if ( $ordinal >= 1000 and $entry =~ m{\A[ok]mp_} ) {
79 $error->( "Ordinal of user-callable entry must be < 1000", $n, $line );
81 if ( $ordinal >= 1000 and $ordinal < 2000 ) {
82 $error->( "Ordinals between 1000 and 1999 are reserved.", $n, $line );
84 if ( exists( $ordinals{ $ordinal } ) ) {
85 $error->( "Ordinal $ordinal has already been used.", $n, $line );
87 $ordinals{ $ordinal } = $entry;
91 $error->( "", $n, $line );
96 my $dir = pop( @dirs );
97 $error->( "Unterminated %if directive.", $dir->{ n
}, $dir->{ line
} );
106 my ( $entries ) = @_;
108 foreach my $entry ( keys( %$entries ) ) {
109 if ( not $entries->{ $entry }->{ obsolete
} ) {
110 my $ordinal = $entries->{ $entry }->{ ordinal
};
111 # omp_alloc and omp_free are C/C++ only functions, skip "1000+ordinal" for them
112 if ( $entry =~ m{\A[ok]mp_} and $entry ne "omp_alloc" and $entry ne "omp_free" and
113 $entry ne "omp_calloc" and $entry ne "omp_realloc" and
114 $entry ne "omp_aligned_alloc" and $entry ne "omp_aligned_calloc" ) {
115 if ( not defined( $ordinal ) ) {
117 "Bad entry \"$entry\": ordinal number is not specified."
120 if ( $ordinal ne "DATA" ) {
121 $entries->{ uc( $entry ) } = { ordinal
=> 1000 + $ordinal };
131 sub generate_output
(\
%$\
%) {
133 my ( $entries, $output, $defs ) = @_;
134 my $lib = %$defs {'NAME'};
138 $bulk = sprintf("NAME %s\n", $lib);
140 $bulk .= sprintf("EXPORTS\n");
141 foreach my $entry ( sort( keys( %$entries ) ) ) {
142 if ( not $entries->{ $entry }->{ obsolete
} ) {
143 $bulk .= sprintf( " %-40s ", $entry );
144 my $ordinal = $entries->{ $entry }->{ ordinal
};
145 if ( defined( $ordinal ) ) {
146 if ( $ordinal eq "DATA" ) {
149 if (not %$defs {'NOORDINALS'}) {
150 $bulk .= "\@" . $ordinal;
157 if ( defined( $output ) ) {
158 write_file
( $output, \
$bulk );
163 }; # sub generate_output
166 # Parse command line.
169 my $input; # The name of input file.
170 my $output; # The name of output file.
174 "output=s" => \
$output,
177 my ( $opt_name, $opt_value ) = @_;
178 my ( $def_name, $def_value );
179 if ( $opt_value =~ m{\A(.*?)=(.*)\z} ) {
180 ( $def_name, $def_value ) = ( $1, $2 );
182 ( $def_name, $def_value ) = ( $opt_value, 1 );
184 $defs{ $def_name } = $def_value;
189 cmdline_error
( "Not enough arguments." );
192 cmdline_error
( "Too many arguments." );
194 $input = shift( @ARGV );
200 my %data = parse_input
( $input, %defs );
201 %data = process
( %data );
202 generate_output
( %data, $output, %defs );
208 # Embedded documentation.
215 B<generate-def.pl> -- Generate def file for OpenMP RTL.
219 B<generate-def.pl> I<OPTION>... I<file>
225 =item B<--define=>I<name>[=I<value>]
227 =item B<-D> I<name>[=I<value>]
229 Define specified name. If I<value> is omitted, I<name> is defined to 1. If I<value> is 0 or empty,
230 name is B<not> defined.
232 =item B<--output=>I<file>
236 Specify output file name. If option is not present, result is printed to stdout.
242 Print full help message and exit.
246 Print short help message and exit.
250 Print very short usage message and exit.
254 Do print informational messages.
258 Print version and exit.
262 Work quiet, do not print informational messages.
272 A name of input file.
278 The script reads input file, process conditional directives, checks content for consistency, and
279 generates output file suitable for linker.
281 =head2 Input File Format
289 Comments start with C<#> symbol and continue to the end of line.
291 =item Conditional Directives
297 A part of file surrounded by C<%ifdef I<name>> and C<%endif> directives is a conditional part -- it
298 has effect only if I<name> is defined in the command line by B<--define> option. C<%ifndef> is a
299 negated version of C<%ifdef> -- conditional part has an effect only if I<name> is B<not> defined.
301 Conditional parts may be nested.
303 =item Export Definitions
309 Symbols starting with C<omp_> or C<kmp_> must have ordinal specified. They are subjects for special
310 processing: each symbol generates two output lines: original one and upper case version. The ordinal
311 number of the second is original ordinal increased by 1000.
313 =item Obsolete Symbols
319 Obsolete symbols look like export definitions prefixed with minus sign. Obsolete symbols do not
320 affect the output, but obsolete symbols and their ordinals cannot be (re)used in export definitions.
326 $ generate-def.pl -D stub -D USE_TCHECK=0 -o libguide.def dllexport