]>
Commit | Line | Data |
---|---|---|
b7b801b2 AA |
1 | /*{ AutoGen5 template -*- C++ -*- |
2 | h | |
3 | (use-modules (srfi srfi-1)) | |
4 | }*/ | |
5 | // Copyright (C) 2023 Free Software Foundation, Inc. | |
6 | ||
7 | // This file is part of the GNU ISO C++ Library. This library is free | |
8 | // software; you can redistribute it and/or modify it under the | |
9 | // terms of the GNU General Public License as published by the | |
10 | // Free Software Foundation; either version 3, or (at your option) | |
11 | // any later version. | |
12 | ||
13 | // This library is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | ||
18 | // Under Section 7 of GPL version 3, you are granted additional | |
19 | // permissions described in the GCC Runtime Library Exception, version | |
20 | // 3.1, as published by the Free Software Foundation. | |
21 | ||
22 | // You should have received a copy of the GNU General Public License and | |
23 | // a copy of the GCC Runtime Library Exception along with this program; | |
24 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
25 | // <http://www.gnu.org/licenses/>. | |
26 | ||
27 | /*{ (dne "// ") }*/ | |
28 | ||
29 | /** @file bits/version.h | |
30 | * This is an internal header file, included by other library headers. | |
31 | * Do not attempt to use it directly. @headername{version} | |
32 | */ | |
33 | ||
34 | // Usage guide: | |
35 | // | |
36 | // In your usual header, do something like: | |
37 | // | |
38 | // #define __glibcxx_want_ranges | |
39 | // #define __glibcxx_want_concepts | |
40 | // #include <bits/version.h> | |
41 | // | |
42 | // This will generate the FTMs you named, and let you use them in your code as | |
43 | // if it was user code. All macros are also exposed under __glibcxx_NAME even | |
44 | // if unwanted, to permit bits and other FTMs to depend on them for condtional | |
45 | // computation without exposing extra FTMs to user code. | |
46 | ||
47 | #pragma GCC system_header | |
48 | ||
49 | #include <bits/c++config.h> | |
50 | /*{ | |
51 | ||
52 | ;; Helper for dealing with autogens redefined (error) | |
53 | (define (ferror msg . args) | |
54 | (error (apply format (cons* #f msg args)))) | |
55 | ||
56 | ;; Helper function that, in the context of a single FTM value, generates the | |
57 | ;; condition expression that fulfills the specification of this value. See the | |
58 | ;; comment block in version.def for an explanation of the format this | |
59 | ;; function parses. | |
60 | (define (generate-cond) | |
61 | (define c++min #f) | |
62 | (define gnu++min #f) | |
63 | (define gthread #f) | |
64 | (define hosted #f) | |
65 | (define c++11-abi #f) | |
66 | (define extra-cond (get "extra_cond")) | |
67 | ||
68 | (define conds '()) | |
69 | (define (prepend x) | |
70 | (if x (set! conds (cons x conds)))) | |
71 | ||
72 | (if (string-null? extra-cond) | |
73 | (set! extra-cond #f)) | |
74 | ||
75 | (let ((cxxmin (get "cxxmin")) | |
76 | (gnuxxmin (get "gnuxxmin")) | |
77 | (getstdcond | |
78 | (lambda (var) | |
79 | (let ((ver (get var))) | |
80 | (if (not (string-null? ver)) | |
81 | (let ((std-cond (get (format #f "stds[~a]" ver)))) | |
82 | (if (string-null? std-cond) | |
83 | (ferror "Standard ~s invalid." ver)) | |
84 | std-cond) | |
85 | #f))))) | |
86 | (set! c++min (getstdcond "cxxmin")) | |
87 | (set! gnu++min (getstdcond "gnuxxmin"))) | |
88 | ||
89 | (let ((process-tristate | |
90 | (lambda (name) | |
91 | (let ((val (get name))) | |
92 | (cond | |
93 | ((equal? val "") #f) ; Don't test | |
94 | ((equal? val "yes") "") ; Test directly | |
95 | ((equal? val "no") "!") ; Invert | |
96 | (else (ferror "Bad ~a value ~a." name val))))))) | |
97 | (set! gthread (process-tristate "gthread")) | |
98 | (set! c++11-abi (process-tristate "cxx11abi")) | |
99 | (set! hosted (process-tristate "hosted"))) | |
100 | ||
101 | (prepend (if extra-cond (format #f "(~a)" extra-cond) #f)) | |
102 | (prepend (if hosted (format #f "~a~a" hosted "_GLIBCXX_HOSTED") #f)) | |
103 | (prepend (if gthread (format #f "~a~a" gthread "defined(_GLIBCXX_HAS_GTHREADS)") #f)) | |
104 | (prepend (if c++11-abi (format #f "~a~a" c++11-abi "_GLIBCXX_USE_CXX11_ABI") #f)) | |
105 | ||
106 | (prepend | |
107 | (let ((strict "defined(__STRICT_ANSI__)") | |
108 | (c++ "__cplusplus")) | |
109 | (cond | |
110 | ((or (and (equal? c++min gnu++min) c++min) | |
111 | (and (not gnu++min) c++min)) | |
112 | ;; If we have both values, and they are equal, or we only have gnu++min, | |
113 | ;; we want to output a simple check. | |
114 | (format #f "(~a ~a)" c++ c++min)) | |
115 | ((and gnu++min c++min) | |
116 | ;; We have differing cases for strict and non-strict modes. | |
117 | (format #f "((~a && ~a ~a) || (!~a && ~a ~a))" | |
118 | strict c++ c++min | |
119 | strict c++ gnu++min)) | |
120 | ((and gnu++min (not c++min)) | |
121 | (format #f "(!~a && (~a ~a))" strict c++ gnu++min)) | |
122 | (else #f)))) | |
123 | (string-join conds " && " 'strict-infix)) | |
124 | ||
125 | ||
126 | }*/ | |
127 | /*{ FOR ftms | |
128 | }*/// /*{ (def-file-line "name") }*/ | |
129 | #if !defined(__cpp_lib_/*{name}*/) | |
130 | /*{ FOR values }*//*{ # | |
131 | ||
132 | This macro block defines two versions of each FTM: | |
133 | ||
134 | 1. __glibcxx_NAME, which is defined unconditionally, and | |
135 | 2. __cpp_lib_NAME, which is defined only if marked as wanted. | |
136 | ||
137 | This allows FTMs to depend on eachother in their definitions without messing | |
138 | with the exported values. | |
139 | ||
140 | This can also be used by bits that do not want to expose FTMs that they can't | |
141 | implement. | |
142 | ||
143 | }*/# /*{(unless (first-for?) "el")}*/if /*{(generate-cond)}*/ | |
144 | # define __glibcxx_/*{name}*/ /*{v}*/L | |
145 | # if defined(__glibcxx_want_all) || defined(__glibcxx_want_/*{name}*/) | |
146 | # define /*{ | |
147 | ;; Compute the name for this FTM based on stdname/name. | |
148 | (if (exist? "stdname") | |
149 | (get "stdname") | |
150 | (format #f "__cpp_lib_~a" (get "name"))) | |
151 | }*/ /*{v}*/L | |
152 | # endif | |
153 | /*{ ENDFOR values | |
154 | }*/# endif | |
155 | #endif /* !defined(__cpp_lib_/*{name}*/) && defined(__glibcxx_want_/*{name}*/) */ | |
156 | #undef __glibcxx_want_/*{name | |
157 | }*//*{ (unless (last-for?) "\n\n" "\n")}*/ | |
158 | /*{ ENDFOR ftms }*//*{ | |
159 | ||
160 | ;; Helper that generates [LO, HI]. | |
161 | (define (closed-int-set lo hi) | |
162 | (iota (+ (- hi lo) 1) lo)) | |
163 | ||
164 | ;; Sanity checking for duplicates and for value order. | |
165 | (let ((ht (make-hash-table (count "ftms")))) | |
166 | (for-each | |
167 | (lambda (idx) | |
168 | (let ((name (get (format #f "ftms[~a].name" idx)))) | |
169 | (if (string-null? name) (ferror "No name for FTM ~a" idx)) | |
170 | (let ((cur (cdr (or (hash-get-handle ht name) '(1 . 0))))) | |
171 | (hash-set! ht name (+ cur 1))))) | |
172 | (closed-int-set (low-lim "ftms") (high-lim "ftms"))) | |
173 | (if (hash-fold | |
174 | (lambda (name count prior) | |
175 | (if (= 1 count) | |
176 | prior | |
177 | (begin | |
178 | (printf "FTM %s appears %d times.\n" name count) | |
179 | #t))) | |
180 | #f ht) | |
181 | (error "Duplicates found."))) | |
182 | ||
183 | (define (check-value-order ftm key order) | |
184 | (let ((valmin 999999)) ; TODO(arsen): bump before year 10000 | |
185 | (for-each | |
186 | (lambda (vidx) | |
187 | (let* ((sval (get (format #f "values[~a].~a" vidx key))) | |
188 | (val (string->number sval))) | |
189 | (unless (string-null? sval) | |
190 | (unless val (ferror "Bad value in FTM ~a" ftm)) | |
191 | (if (order val valmin) | |
192 | (ferror "Found inverted ~s value in FTM ~a: ~a" key ftm sval)) | |
193 | (set! valmin val)))) | |
194 | (closed-int-set (low-lim "values") (high-lim "values"))))) | |
195 | ||
196 | }*//*{ FOR ftms }*//*{# | |
197 | Check for values that are in ascending order. Because it is generally the | |
198 | case that FTMs increase as the values of tests they probe for do, we check | |
199 | them to prevent simple, silly errors. | |
200 | ||
201 | We're iterating in a separate FOR block rather than in pure Guile since, for | |
202 | some reason, high-lim and low-lim do not work with complex names that include | |
203 | periods and indices (whereas exist? and others do). | |
204 | }*//*{ | |
205 | (let ((ftm (get "name"))) | |
206 | (check-value-order (get "name") "v" >) | |
207 | (check-value-order (get "name") "cxxmin" >) | |
208 | (check-value-order (get "name") "gnuxxmin" >)) | |
209 | }*//*{ ENDFOR ftms }*/ | |
210 | #undef __glibcxx_want_all |