1 #include <string> 2 #include <string_view> 3 #include <map> 4 #include <set> 5 #include <algorithm> 6 #include <iterator> 7 #include <iostream> 8 9 // This is a slow larval-stage kludge to help massage the generated man 10 // pages. It's used like this: 11 const std::string_view usage = R"( 12 Takes on stdin, whitespace-separated words of the form 13 14 [bits/]stl_foo.h 15 [bits/]std_foo.h 16 17 and writes on stdout the nearest matching standard header name. 18 19 Takes no command-line arguments. 20 )"; 21 22 // List of standard headers 23 std::set<std::string_view> std_headers; 24 // Map of partial header filenames to standard headers. 25 std::map<std::string_view, std::string_view> headers; 26 27 void init_map() 28 { 29 // Enter the glamourous world of data entry!! Maintain these! 30 // Because the map_header function removes common prefixes and suffixes, 31 // a header "bits/st[dl]_foo.h" will automatically map to "foo" if that 32 // is a standard header, so we don't need to list those cases here. 33 headers["atomic_base.h"] = "atomic"; 34 headers["atomic_lockfree_defines.h"] = "atomic"; 35 headers["atomic_timed_wait.h"] = "atomic"; 36 headers["atomic_wait.h"] = "atomic"; 37 headers["algorithmfwd.h"] = "algorithm"; 38 headers["algo.h"] = "algorithm"; 39 headers["algobase.h"] = "algorithm"; 40 headers["ranges_algo.h"] = "algorithm"; 41 headers["ranges_algobase.h"] = "algorithm"; 42 headers["heap.h"] = "algorithm"; 43 headers["chrono_io.h"] = "chrono"; 44 headers["parse_numbers.h"] = "chrono"; 45 headers["exception_ptr.h"] = "exception"; 46 headers["nested_exception.h"] = "exception"; 47 headers["fs_dir.h"] = "filesystem"; 48 headers["fs_fwd.h"] = "filesystem"; 49 headers["fs_ops.h"] = "filesystem"; 50 headers["fs_path.h"] = "filesystem"; 51 headers["unicode.h"] = "format"; 52 headers["unicode-data.h"] = "format"; 53 headers["binders.h"] = "functional"; 54 headers["function.h"] = "functional"; 55 headers["functional_hash.h"] = "functional"; 56 headers["mofunc_impl.h"] = "functional"; 57 headers["move_only_function.h"] = "functional"; 58 headers["invoke.h"] = "functional"; 59 headers["ranges_cmp.h"] = "functional"; 60 headers["refwrap.h"] = "functional"; 61 headers["elements_of.h"] = "generator"; 62 headers["quoted_string.h"] = "iomanip"; 63 headers["ios_base.h"] = "ios"; 64 headers["basic_ios.h"] = "ios"; 65 headers["basic_ios.tcc"] = "ios"; 66 headers["iosfwd.h"] = "iosfwd"; 67 headers["iostream.h"] = "iostream"; 68 headers["iterator_base_funcs.h"] = "iterator"; 69 headers["iterator_base_types.h"] = "iterator"; 70 headers["stream_iterator.h"] = "iterator"; 71 headers["streambuf_iterator.h"] = "iterator"; 72 headers["iterator_concepts.h"] = "iterator"; 73 headers["max_size_type.h"] = "iterator"; 74 headers["range_access.h"] = "iterator"; 75 headers["codecvt.h"] = "locale"; 76 headers["c++locale.h"] = "locale"; 77 headers["localefwd.h"] = "locale"; 78 headers["ctype_base.h"] = "locale"; 79 headers["locale_classes.h"] = "locale"; 80 headers["locale_classes.tcc"] = "locale"; 81 headers["locale_facets.h"] = "locale"; 82 headers["locale_facets.tcc"] = "locale"; 83 headers["locale_facets_nonio.h"] = "locale"; 84 headers["locale_facets_nonio.tcc"] = "locale"; 85 headers["locale_conv.h"] = "locale"; 86 headers["multimap.h"] = "map"; 87 headers["memoryfwd.h"] = "memory"; 88 headers["align.h"] = "memory"; 89 headers["alloc_traits.h"] = "memory"; 90 headers["allocated_ptr.h"] = "memory"; 91 headers["auto_ptr.h"] = "memory"; 92 headers["construct.h"] = "memory"; 93 headers["allocator.h"] = "memory"; 94 headers["new_allocator.h"] = "memory"; 95 headers["raw_storage_iter.h"] = "memory"; 96 headers["tempbuf.h"] = "memory"; 97 headers["uninitialized.h"] = "memory"; 98 headers["shared_ptr.h"] = "memory"; 99 headers["shared_ptr_base.h"] = "memory"; 100 headers["shared_ptr_atomic.h"] = "memory"; 101 headers["unique_ptr.h"] = "memory"; 102 headers["ranges_uninitialized.h"] = "memory"; 103 headers["ptr_traits.h"] = "memory"; 104 headers["uses_allocator.h"] = "memory"; 105 headers["uses_allocator_args.h"] = "memory"; 106 headers["out_ptr.h"] = "memory"; 107 headers["memory_resource.h"] = "memory_resource"; 108 headers["unique_lock.h"] = "mutex"; 109 headers["sat_arith.h"] = "numeric"; 110 headers["ostream_insert.h"] = "ostream"; 111 headers["uniform_int_dist.h"] = "random"; 112 headers["ranges_base.h"] = "ranges"; 113 headers["ranges_to.h"] = "ranges"; 114 headers["ranges_util.h"] = "ranges"; 115 headers["regex_automaton.h"] = "regex"; 116 headers["regex_automaton.tcc"] = "regex"; 117 headers["regex_compiler.h"] = "regex"; 118 headers["regex_compiler.tcc"] = "regex"; 119 headers["regex_constants.h"] = "regex"; 120 headers["regex_error.h"] = "regex"; 121 headers["regex_executor.h"] = "regex"; 122 headers["regex_executor.tcc"] = "regex"; 123 headers["regex_scanner.h"] = "regex"; 124 headers["regex_scanner.tcc"] = "regex"; 125 headers["semaphore_base.h"] = "semaphore"; 126 headers["multiset.h"] = "set"; 127 headers["node_handle.h"] = "set"; 128 headers["functexcept.h"] = "stdexcept"; 129 headers["char_traits.h"] = "string"; 130 headers["stringfwd.h"] = "string"; 131 headers["postypes.h"] = "string"; 132 headers["basic_string.h"] = "string"; 133 headers["basic_string.tcc"] = "string"; 134 headers["cow_string.h"] = "string"; 135 headers["string_view.tcc"] = "string_view"; 136 headers["this_thread_sleep.h"] = "thread"; 137 headers["tree.h"] = "map"; 138 headers["hashtable.h"] = "unordered_map"; 139 headers["hashtable_policy.h"] = "unordered_map"; 140 headers["move.h"] = "utility"; 141 headers["pair.h"] = "utility"; 142 headers["relops.h"] = "utility"; 143 headers["gslice.h"] = "valarray"; 144 headers["gslice_array.h"] = "valarray"; 145 headers["indirect_array.h"] = "valarray"; 146 headers["mask_array.h"] = "valarray"; 147 headers["slice_array.h"] = "valarray"; 148 headers["valarray_after.h"] = "valarray"; 149 headers["valarray_before.h"] = "valarray"; 150 headers["valarray_array.h"] = "valarray"; 151 headers["valarray_array.tcc"] = "valarray"; 152 headers["valarray_meta.h"] = "valarray"; 153 headers["bvector.h"] = "vector"; 154 155 //headers["concurrence.h"] who knows 156 //headers["atomicity.h"] who knows 157 158 headers["abs.h"] = "cstdlib"; 159 headers["specfun.h"] = "cmath"; 160 161 // This list is complete as of the April 2024 working draft. 162 std_headers = { 163 "algorithm", "any", "array", "atomic", 164 "barrier", "bit", "bitset", 165 "charconv", "chrono", "codecvt", "compare", "complex", 166 "concepts", "condition_variable", "coroutine", 167 "debugging", "deque", 168 "exception", "execution", "expected", 169 "filesystem", "flat_set", "flat_map", "format", "forward_list", 170 "fstream", "functional", "future", 171 "generator", 172 "hazard_pointer", 173 "initializer_list", "iomanip", "ios", "iosfwd", 174 "iostream", "istream", "iterator", 175 "latch", "limits", "linalg", "list", "locale", 176 "map", "mdspan", "memory", "memory_resource", "mutex", 177 "new", "numbers", "numeric", 178 "optional", "ostream", 179 "print", 180 "queue", 181 "random", "ranges", "ratio", "rcu", "regex", 182 "scoped_allocator", "semaphore", "set", "shared_mutex", 183 "source_location", "span", "spanstream", "sstream", 184 "stack", "stacktrace", "stdexcept", "stdfloat", "stop_token", 185 "streambuf", "string", "string_view", "strstream", 186 "syncstream", "system_error", 187 "text_encoding", "thread", "tuple", "type_traits", 188 "typeindex", "typeinfo", 189 "unordered_map", "unordered_set", "utility", 190 "valarray", "variant", "vector", "version", 191 192 "cassert", "cctype", "cerrno", "cfenv", "cfloat", 193 "cinttypes", "climits", "clocale", "cmath", "csetjmp", 194 "csignal", "cstdarg", "cstddef", "cstdint", "cstdio", 195 "cstdlib", "cstring", "ctime", "cuchar", "cwchar", 196 "cwctype", 197 198 "assert.h", "ctype.h", "errno.h", "fenv.h", "float.h", 199 "inttypes.h", "limits.h", "locale.h", "math.h", "setjmp.h", 200 "signal.h", "stdarg.h", "stddef.h", "stdint.h", "stdio.h", 201 "stdlib.h", "string.h", "time.h", "uchar.h", "wchar.h", 202 "wctype.h", 203 }; 204 205 // In case we missed any: 206 for (const auto& h : headers) 207 std_headers.insert(h.second); 208 } 209 210 211 std::string_view map_header (std::string_view header) 212 { 213 // if it doesn't contain a "." then it's already a std header 214 if (!header.contains('.')) 215 { 216 // make sure it's in the set: 217 std_headers.insert(header); 218 return header; 219 } 220 221 for (std::string_view prefix : {"bits/", "stl_", "std_"}) 222 if (header.starts_with(prefix)) 223 header.remove_prefix(prefix.size()); 224 225 if (auto it = headers.find(header); it != headers.end()) 226 return it->second; 227 228 for (std::string_view ext : {".h", ".tcc"}) 229 if (header.ends_with(ext)) 230 { 231 header.remove_suffix(ext.size()); 232 break; 233 } 234 235 if (auto it = std_headers.find(header); it != std_headers.end()) 236 return *it; 237 238 return {}; 239 } 240 241 std::string map_header_or_complain (std::string header) 242 { 243 // For <experimental/xxx.h> and <tr1/xxx.h> try to map <xxx.h> 244 // then add the directory back to it. 245 if (header.contains('.')) 246 for (std::string_view dir : {"experimental/", "tr1/"}) 247 if (header.starts_with(dir)) 248 { 249 auto h = map_header(header.substr(dir.size())); 250 if (!h.empty()) 251 return std::string(dir) + std::string(h); 252 return std::string(header); 253 } 254 255 if (auto mapped = map_header(header); !mapped.empty()) 256 return std::string(mapped); 257 258 std::cerr << "Could not map <" << header << "> to a standard header\n"; 259 return std::string(header); 260 } 261 262 263 int main (int argc, char** argv) 264 { 265 if (argc > 1) 266 { 267 std::cerr << "Usage: " << argv[0] << '\n' << usage; 268 return 1; 269 } 270 271 init_map(); 272 273 std::transform(std::istream_iterator<std::string>(std::cin), {}, 274 std::ostream_iterator<std::string>(std::cout), 275 map_header_or_complain); 276 } 277