| // Copyright (c) 2025 The BoringSSL Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| //go:build ignore |
| |
| // extract_identifiers_clang_json parses the BoringSSL public includes and (for now) |
| // outputs a report of all identifiers defined therein. Sample usage: |
| // |
| // for f in include/openssl/*.h; do echo "#include <${f#include/}>"; done |\ |
| // clang++ -x c++ -std=c++17 -Iinclude -fsyntax-only -Xclang -ast-dump=json - \ |
| // go run util/extract_identifiers_clang_json.go > extract_identifiers.txt |
| // |
| // Note that right now the output of this tool is for human use only. |
| // The tool will likely be changed further for the purpose of symbol prefixing |
| // and auditing thereof. |
| |
| package main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "os" |
| |
| "boringssl.googlesource.com/boringssl.git/util/idextractor" |
| ) |
| |
| var ( |
| dumpTree = flag.Bool("dump_tree", false, "dump syntax tree while processing") |
| dumpFullTree = flag.Bool("dump_full_tree", false, "dump syntax tree while processing including system headers") |
| keepGoing = flag.Bool("keep_going", false, "continue even after errors") |
| language = flag.String("language", "C", "language to consider the source to be") |
| globalSymbolsOnly = flag.Bool("global_symbols_only", false, "only output a list of names that may become (part of) linker symbols and are not namespaced") |
| ) |
| |
| func reportIdentifierGlobalSymbolsOnly(id idextractor.IdentifierInfo) error { |
| // NOTE: This is over-exporting. |
| // At least for quite a while we can't namespace the |
| // enum, struct and union tags either |
| // as they may be forward declared by callers. |
| // The idea is to first get this overzealous namespacing to work, |
| // and then to remove those forward declaration prone symbols |
| // at least initially (and possibly namespace them then one by one). |
| if id.Symbol == id.Identifier && id.Linkage != "static" && id.Tag != "typedef" && id.Tag != "using" { |
| fmt.Printf("%s\n", id.Identifier) |
| } |
| return nil |
| } |
| |
| var seen = map[string]string{} |
| |
| func reportIdentifierVerbose(id idextractor.IdentifierInfo) error { |
| linkage := "" |
| if id.Linkage != "" { |
| linkage = id.Linkage + " " |
| } |
| declaration := fmt.Sprintf("%s%s %s;", linkage, id.Tag, id.Symbol) |
| key := id.Symbol |
| previous, found := seen[key] |
| if found { |
| if previous != declaration { |
| return fmt.Errorf("duplicate distinct definition of %v: %v and %v", key, previous, declaration) |
| } |
| return nil |
| } |
| seen[key] = declaration |
| |
| // Append some debug info. |
| // This might be used later to generate symbol renaming headers, |
| // but is generally useful to humans debugging this tool's output. |
| var suffix string |
| if id.File != "" { |
| suffix += fmt.Sprintf(" %s:%v (%v-%v)", id.File, id.Line, id.Start, id.End) |
| } |
| for _, arg := range id.FunctionArgs { |
| if arg == "" { |
| arg = "_" |
| } |
| suffix += " " + arg |
| } |
| if suffix != "" { |
| suffix = " //" + suffix |
| } |
| fmt.Printf("%s%s\n", declaration, suffix) |
| return nil |
| } |
| |
| // Main is the main program. |
| func Main() error { |
| report := reportIdentifierVerbose |
| if *globalSymbolsOnly { |
| report = reportIdentifierGlobalSymbolsOnly |
| } |
| x := idextractor.New(report, idextractor.Options{ |
| DumpTree: *dumpTree, |
| DumpFullTree: *dumpFullTree, |
| KeepGoing: *keepGoing, |
| Language: *language, |
| }) |
| return x.Parse(os.Stdin) |
| } |
| |
| // main runs Main turning errors into exit codes. |
| func main() { |
| flag.Parse() |
| err := Main() |
| if err != nil { |
| log.Panicf("error returned from Main: %v", err) |
| } |
| } |