kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/extractor/objc_bazel_support.cc (about)

     1  /*
     2   * Copyright 2016 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #include "objc_bazel_support.h"
    18  
    19  #include <stdio.h>
    20  
    21  #include <algorithm>
    22  #include <cstddef>
    23  #include <cstdio>
    24  #include <sstream>
    25  #include <string>
    26  #include <vector>
    27  
    28  #include "google/protobuf/repeated_ptr_field.h"
    29  #include "llvm/ADT/StringRef.h"
    30  #include "re2/re2.h"
    31  #include "third_party/bazel/src/main/protobuf/extra_actions_base.pb.h"
    32  
    33  namespace kythe {
    34  
    35  // This is inspiried by Python's commands.mkarg
    36  // https://hg.python.org/cpython/file/tip/Lib/commands.py#l81
    37  std::string SanitizeArgument(const std::string& s) {
    38    if (s.find('\'') == std::string::npos) {
    39      // There are no single quotes, so we can make the string safe by putting it
    40      // in single quotes.
    41      return "'" + s + "'";
    42    }
    43    // There are single quotes in the string, so we will wrap it in double quotes
    44    // and escape backslash, double-quote, dollar, and back-tick.
    45    std::string ret = s;
    46    RE2::GlobalReplace(&ret, R"(([\\"$`]))", R"(\\\1)");
    47    return "\"" + ret + "\"";
    48  }
    49  
    50  std::string BuildEnvVarCommandPrefix(
    51      const google::protobuf::RepeatedPtrField<blaze::EnvironmentVariable>&
    52          vars) {
    53    std::stringstream ret;
    54    for (const auto& env : vars) {
    55      // Neither name nor value are validated or sanitized.
    56      // This really should be unnecessary, but we don't have any guarantees.
    57      if (RE2::FullMatch(env.name(), "[a-zA-Z_][a-zA-Z_0-9]*")) {
    58        ret << env.name() << "=" << SanitizeArgument(env.value()) << " ";
    59      }
    60    }
    61    return ret.str();
    62  }
    63  
    64  std::string RunScript(const std::string& cmd) {
    65    char buffer[256];
    66    std::string output = "";
    67    FILE* f = popen(cmd.c_str(), "r");
    68    if (!f) {
    69      return output;
    70    }
    71    while (!feof(f)) {
    72      if (fgets(buffer, 256, f) != nullptr) {
    73        output += buffer;
    74      }
    75    }
    76    pclose(f);
    77    return std::string(llvm::StringRef(output).trim());
    78  }
    79  
    80  void FillWithFixedArgs(std::vector<std::string>& args,
    81                         const blaze::CppCompileInfo& ci,
    82                         const std::string& devdir, const std::string& sdkroot) {
    83    args.push_back(ci.tool());
    84    for (const auto& i : ci.compiler_option()) {
    85      std::string arg = i;
    86      RE2::GlobalReplace(&arg, "__BAZEL_XCODE_DEVELOPER_DIR__", devdir);
    87      RE2::GlobalReplace(&arg, "__BAZEL_XCODE_SDKROOT__", sdkroot);
    88      args.push_back(arg);
    89    }
    90    // If the command-line did not specify "-c x.m" specifically, include the
    91    // primary source at the end of the argument list.
    92    if (std::find(args.begin(), args.end(), "-c") == args.end()) {
    93      args.push_back(ci.source_file());
    94    }
    95  }
    96  
    97  void FillWithFixedArgs(std::vector<std::string>& args,
    98                         const blaze::SpawnInfo& si, const std::string& devdir,
    99                         const std::string& sdkroot) {
   100    for (const auto& i : si.argument()) {
   101      std::string arg = i;
   102      RE2::GlobalReplace(&arg, "__BAZEL_XCODE_DEVELOPER_DIR__", devdir);
   103      RE2::GlobalReplace(&arg, "__BAZEL_XCODE_SDKROOT__", sdkroot);
   104      args.push_back(arg);
   105    }
   106  }
   107  
   108  }  // namespace kythe