Update ChangeLog.old/ChangeLog.23.
[glibc.git] / scripts / versions.awk
blob565233e5297e5eaf6b77e0eacb58e75e4550a30e
1 # Combine version map fragments into version scripts for our shared objects.
2 # Copyright (C) 1998-2021 Free Software Foundation, Inc.
3 # Written by Ulrich Drepper <drepper@cygnus.com>, 1998.
5 # This script expects the following variables to be defined:
6 # defsfile name of Versions.def file
7 # buildroot name of build directory with trailing slash
8 # move_if_change move-if-change command
10 # Read definitions for the versions.
11 BEGIN {
12 lossage = 0;
14 nlibs=0;
15 while (getline < defsfile) {
16 if (/^[a-zA-Z0-9_.]+ \{/) {
17 libs[$1] = 1;
18 curlib = $1;
19 while (getline < defsfile && ! /^}/) {
20 if ($2 == "=") {
21 renamed[curlib "::" $1] = $3;
23 else
24 versions[curlib "::" $1] = 1;
28 close(defsfile);
30 tmpfile = buildroot "Versions.tmp";
31 # POSIX sort needed.
32 sort = "sort -t. -k 1,1 -k 2n,2n -k 3 > " tmpfile;
35 # GNU awk does not implement the ord and chr functions.
36 # <https://www.gnu.org/software/gawk/manual/html_node/Ordinal-Functions.html>
37 # says that they are "written very nicely", using code similar to what
38 # is included here.
39 function chr(c) {
40 return sprintf("%c", c)
43 BEGIN {
44 for (c = 1; c < 127; c++) {
45 ord_table[chr(c)] = c;
49 function ord(c) {
50 if (ord_table[c]) {
51 return ord_table[c];
52 } else {
53 printf("Invalid character reference: '%c'\n", c) > "/dev/stderr";
54 ++lossage;
58 # Remove comment lines.
59 /^ *#/ {
60 next;
63 # This matches the beginning of the version information for a new library.
64 /^[a-zA-Z0-9_.]+/ {
65 actlib = $1;
66 if (!libs[$1]) {
67 printf("no versions defined for %s\n", $1) > "/dev/stderr";
68 ++lossage;
70 next;
73 # This matches the beginning of a new version for the current library.
74 /^ [A-Za-z_]/ {
75 if (renamed[actlib "::" $1])
76 actver = renamed[actlib "::" $1];
77 else if (!versions[actlib "::" $1] && $1 != "GLIBC_PRIVATE") {
78 printf("version %s not defined for %s\n", $1, actlib) > "/dev/stderr";
79 ++lossage;
81 else
82 actver = $1;
83 next;
86 # This matches lines with names to be added to the current version in the
87 # current library. This is the only place where we print something to
88 # the intermediate file.
89 /^ / {
90 sortver=actver
91 # Ensure GLIBC_ versions come always first
92 sub(/^GLIBC_/," GLIBC_",sortver)
93 printf("%s %s %s\n", actlib, sortver, $0) | sort;
96 # Some targets do not set the ABI baseline for libdl. As a result,
97 # symbols originally in libdl need to be moved under historic symbol
98 # versions, without altering the baseline version for libc itself.
99 /^ *!libc_pre_versions/ {
100 libc_pre_versions_active = 1;
103 function libc_pre_versions() {
104 # No local: * here, so that we do not have to update this script
105 # if symbols are moved into libc. The abilist files and the other
106 # targets (with a real GLIBC_2.0 baseline) provide testing
107 # coverage.
108 printf("\
109 GLIBC_2.0 {\n\
110 };\n\
111 GLIBC_2.1 {\n\
112 } GLIBC_2.0;\n\
113 ") > outfile;
114 return "GLIBC_2.1";
117 function closeversion(name, oldname) {
118 printf(" local:\n *;\n") > outfile;
119 # This version inherits from the last one only if they
120 # have the same nonnumeric prefix, i.e. GLIBC_x.y and GLIBC_x.z
121 # or FOO_x and FOO_y but not GLIBC_x and FOO_y.
122 pfx = oldname;
123 sub(/[0-9.]+/,".+",pfx);
124 if (oldname == "" || name !~ pfx) print "};" > outfile;
125 else printf("} %s;\n", oldname) > outfile;
128 function close_and_move(name, real_name) {
129 close(name);
130 system(move_if_change " " name " " real_name " >&2");
133 # ELF hash, for use with symbol versions.
134 function elf_hash(s, i, acc) {
135 acc = 0;
136 for (i = 1; i <= length(s); ++i) {
137 acc = and(lshift(acc, 4) + ord(substr(s, i, 1)), 0xffffffff);
138 top = and(acc, 0xf0000000);
139 acc = and(xor(acc, rshift(top, 24)), compl(top));
141 return acc;
144 # Now print the accumulated information.
145 END {
146 close(sort);
148 if (lossage) {
149 system("rm -f " tmpfile);
150 exit 1;
153 oldlib = "";
154 oldver = "";
155 real_first_ver_header = buildroot "first-versions.h"
156 first_ver_header = real_first_ver_header "T"
157 printf("#ifndef _FIRST_VERSIONS_H\n") > first_ver_header;
158 printf("#define _FIRST_VERSIONS_H\n") > first_ver_header;
159 real_ldbl_compat_header = buildroot "ldbl-compat-choose.h"
160 ldbl_compat_header = real_ldbl_compat_header "T"
161 printf("#ifndef _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header;
162 printf("#define _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header;
163 printf("#ifndef LONG_DOUBLE_COMPAT\n") > ldbl_compat_header;
164 printf("# error LONG_DOUBLE_COMPAT not defined\n") > ldbl_compat_header;
165 printf("#endif\n") > ldbl_compat_header;
166 printf("version-maps =");
167 while (getline < tmpfile) {
168 if ($1 != oldlib) {
169 if (oldlib != "") {
170 closeversion(oldver, veryoldver);
171 oldver = "";
172 close_and_move(outfile, real_outfile);
174 oldlib = $1;
175 real_outfile = buildroot oldlib ".map";
176 outfile = real_outfile "T";
177 if ($1 == "libc" && libc_pre_versions_active) {
178 veryoldver = libc_pre_versions();
179 } else {
180 veryoldver = "";
182 printf(" %s.map", oldlib);
184 if ($2 != oldver) {
185 if (oldver != "") {
186 closeversion(oldver, veryoldver);
187 veryoldver = oldver;
189 printf("%s {\n global:\n", $2) > outfile;
190 oldver = $2;
192 printf(" ") > outfile;
193 for (n = 3; n <= NF; ++n) {
194 printf(" %s", $n) > outfile;
195 sym = $n;
196 sub(";", "", sym);
197 first_ver_macro = "FIRST_VERSION_" oldlib "_" sym;
198 if (!(first_ver_macro in first_ver_seen) \
199 && oldver ~ "^GLIBC_[0-9]" \
200 && sym ~ "^[A-Za-z0-9_]*$") {
201 ver_val = oldver;
202 printf("#define %s_STRING \"%s\"\n", first_ver_macro, ver_val) > first_ver_header;
203 printf("#define %s_HASH 0x%x\n", first_ver_macro, elf_hash(ver_val)) > first_ver_header;
204 gsub("\\.", "_", ver_val);
205 printf("#define %s %s\n", first_ver_macro, ver_val) > first_ver_header;
206 first_ver_seen[first_ver_macro] = 1;
207 if (oldlib == "libc" || oldlib == "libm") {
208 printf("#if LONG_DOUBLE_COMPAT (%s, %s)\n",
209 oldlib, ver_val) > ldbl_compat_header;
210 printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) a\n",
211 oldlib, sym) > ldbl_compat_header;
212 printf("#else\n") > ldbl_compat_header;
213 printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) b\n",
214 oldlib, sym) > ldbl_compat_header;
215 printf("#endif\n") > ldbl_compat_header;
219 printf("\n") > outfile;
221 printf("\n");
222 printf("#endif /* first-versions.h */\n") > first_ver_header;
223 printf("#endif /* ldbl-compat-choose.h */\n") > ldbl_compat_header;
224 closeversion(oldver, veryoldver);
225 close_and_move(outfile, real_outfile);
226 close_and_move(first_ver_header, real_first_ver_header);
227 close_and_move(ldbl_compat_header, real_ldbl_compat_header);
228 #system("rm -f " tmpfile);