Home | History | Annotate | Line # | Download | only in doxygen
      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