예제 #1
0
error_code FileOutputBuffer::create(StringRef FilePath,
                                    size_t Size,
                                    OwningPtr<FileOutputBuffer> &Result,
                                    unsigned Flags) {
  // If file already exists, it must be a regular file (to be mappable).
  sys::fs::file_status Stat;
  error_code EC = sys::fs::status(FilePath, Stat);
  switch (Stat.type()) {
    case sys::fs::file_type::file_not_found:
      // If file does not exist, we'll create one.
      break;
    case sys::fs::file_type::regular_file: {
        // If file is not currently writable, error out.
        // FIXME: There is no sys::fs:: api for checking this.
        // FIXME: In posix, you use the access() call to check this.
      }
      break;
    default:
      if (EC)
        return EC;
      else
        return make_error_code(errc::operation_not_permitted);
  }

  // Delete target file.
  bool Existed;
  EC = sys::fs::remove(FilePath, Existed);
  if (EC)
    return EC;

  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
  // If requested, make the output file executable.
  if (Flags & F_executable)
    Mode |= sys::fs::all_exe;

  // Create new file in same directory but with random name.
  SmallString<128> TempFilePath;
  int FD;
  EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD,
                                 TempFilePath, Mode);
  if (EC)
    return EC;

  OwningPtr<mapped_file_region> MappedFile(new mapped_file_region(
      FD, true, mapped_file_region::readwrite, Size, 0, EC));
  if (EC)
    return EC;

  Result.reset(new FileOutputBuffer(MappedFile.get(), FilePath, TempFilePath));
  if (Result)
    MappedFile.take();

  return error_code::success();
}
예제 #2
0
 bool Preprocessor::HandleInclude(size_t line_no, Tokenizer & tok){
     bool issection = false;
     if (tok.next_token() == "section"){
         issection = true;
         tok.next_token();
     }
     if (tok.get_type() != Tokenizer::Type::String){
         throw Exception::Error("Include name must be quoted string; got `" + tok.get_string() + "`.");
     }
     MappedFile mfile;
     std::string section = "";
     if (issection){
         section = tok.get_string();
         trim_ends(section);
         mfile = filedata;
     }
     else{
         std::string file = tok;
         trim_ends(file);
         size_t pos = file.find_first_of("?");
         if (pos != std::string::npos){
             section = file.substr(pos + 1);
             file.erase(file.begin() + pos, file.end());
         }
         else{
             if (tok.next_token()){
                 if (tok == "section"){
                     if (tok.next_token().get_type() == Tokenizer::Type::String){
                         section = tok.get_string();
                         trim_ends(section);
                     }
                     else{
                         throw Exception::Error("String expected after `section`; got `" + tok.get_string() + "`.");
                     }
                 }
                 else{
                     throw Exception::Error("Unknown include specifier `" + tok.get_string() + "`. Did you mean to use `section`?");
                 }
             }
         }
         mfile = MappedFile(file, include_paths);
     }
     size_t file_number;// = push_file(filenames, mfile.name());
     std::string test_name = "___ONCE_INCLUDE " + section + "?" + mfile.name();
     if (Defined(section, test_name)){
         currentData.push_back('\n');
         return true;
     }
     //currentData += "#line 1 " + std::to_string(file_number) + "\n";
     defines.push_back(&sections[currentSection].defines);
     Preprocessor p = Preprocessor(mfile, include_paths, defines, filenames, section);
     auto newSections = p.Preprocess();
     auto& back = *defines.back();
     defines.pop_back();
     for (auto & def : back){
         Define(def.first, def.second);
     }
     file_number = push_file(filenames, filedata.name());
     currentData += newSections.at(section).data;
     currentData.push_back('\n');
     currentData += "#line " + std::to_string(line_no) + " " + std::to_string(file_number) + "\n";
     return true;
 }