Command run: jq <compile_commands.json -r 'map(.file)|.[]' | grep -v '/generated/' | parallel clang-tidy -p compile_commands.json -checks=-*,google-readability-casting --fix Manual fixes applied in src/nix-env/nix-env.cc, src/libstore/store-api.cc Change-Id: I406b4be9368c557ca59329bf6f7002704e955f8d Reviewed-on: https://cl.tvl.fyi/c/depot/+/1557 Tested-by: BuildkiteCI Reviewed-by: glittershark <grfn@gws.fyi> Reviewed-by: tazjin <mail@tazj.in>
		
			
				
	
	
		
			219 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "libutil/args.hh"
 | |
| 
 | |
| #include "libutil/hash.hh"
 | |
| 
 | |
| namespace nix {
 | |
| 
 | |
| Args::FlagMaker Args::mkFlag() { return FlagMaker(*this); }
 | |
| 
 | |
| Args::FlagMaker::~FlagMaker() {
 | |
|   assert(!flag->longName.empty());
 | |
|   args.longFlags[flag->longName] = flag;
 | |
|   if (flag->shortName != 0) {
 | |
|     args.shortFlags[flag->shortName] = flag;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Args::parseCmdline(const Strings& _cmdline) {
 | |
|   Strings pendingArgs;
 | |
|   bool dashDash = false;
 | |
| 
 | |
|   Strings cmdline(_cmdline);
 | |
| 
 | |
|   for (auto pos = cmdline.begin(); pos != cmdline.end();) {
 | |
|     auto arg = *pos;
 | |
| 
 | |
|     /* Expand compound dash options (i.e., `-qlf' -> `-q -l -f',
 | |
|        `-j3` -> `-j 3`). */
 | |
|     if (!dashDash && arg.length() > 2 && arg[0] == '-' && arg[1] != '-' &&
 | |
|         (isalpha(arg[1]) != 0)) {
 | |
|       *pos = std::string("-") + arg[1];
 | |
|       auto next = pos;
 | |
|       ++next;
 | |
|       for (unsigned int j = 2; j < arg.length(); j++) {
 | |
|         if (isalpha(arg[j]) != 0) {
 | |
|           cmdline.insert(next, std::string("-") + arg[j]);
 | |
|         } else {
 | |
|           cmdline.insert(next, std::string(arg, j));
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       arg = *pos;
 | |
|     }
 | |
| 
 | |
|     if (!dashDash && arg == "--") {
 | |
|       dashDash = true;
 | |
|       ++pos;
 | |
|     } else if (!dashDash && std::string(arg, 0, 1) == "-") {
 | |
|       if (!processFlag(pos, cmdline.end())) {
 | |
|         throw UsageError(format("unrecognised flag '%1%'") % arg);
 | |
|       }
 | |
|     } else {
 | |
|       pendingArgs.push_back(*pos++);
 | |
|       if (processArgs(pendingArgs, false)) {
 | |
|         pendingArgs.clear();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   processArgs(pendingArgs, true);
 | |
| }
 | |
| 
 | |
| void Args::printHelp(const std::string& programName, std::ostream& out) {
 | |
|   std::cout << "Usage: " << programName << " <FLAGS>...";
 | |
|   for (auto& exp : expectedArgs) {
 | |
|     std::cout << renderLabels({exp.label});
 | |
|     // FIXME: handle arity > 1
 | |
|     if (exp.arity == 0) {
 | |
|       std::cout << "...";
 | |
|     }
 | |
|     if (exp.optional) {
 | |
|       std::cout << "?";
 | |
|     }
 | |
|   }
 | |
|   std::cout << "\n";
 | |
| 
 | |
|   auto s = description();
 | |
|   if (!s.empty()) {
 | |
|     std::cout << "\nSummary: " << s << ".\n";
 | |
|   }
 | |
| 
 | |
|   if (!longFlags.empty() != 0u) {
 | |
|     std::cout << "\n";
 | |
|     std::cout << "Flags:\n";
 | |
|     printFlags(out);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Args::printFlags(std::ostream& out) {
 | |
|   Table2 table;
 | |
|   for (auto& flag : longFlags) {
 | |
|     if (hiddenCategories.count(flag.second->category) != 0u) {
 | |
|       continue;
 | |
|     }
 | |
|     table.push_back(std::make_pair(
 | |
|         (flag.second->shortName != 0
 | |
|              ? std::string("-") + flag.second->shortName + ", "
 | |
|              : "    ") +
 | |
|             "--" + flag.first + renderLabels(flag.second->labels),
 | |
|         flag.second->description));
 | |
|   }
 | |
|   printTable(out, table);
 | |
| }
 | |
| 
 | |
| bool Args::processFlag(Strings::iterator& pos, Strings::iterator end) {
 | |
|   assert(pos != end);
 | |
| 
 | |
|   auto process = [&](const std::string& name, const Flag& flag) -> bool {
 | |
|     ++pos;
 | |
|     std::vector<std::string> args;
 | |
|     for (size_t n = 0; n < flag.arity; ++n) {
 | |
|       if (pos == end) {
 | |
|         if (flag.arity == ArityAny) {
 | |
|           break;
 | |
|         }
 | |
|         throw UsageError(format("flag '%1%' requires %2% argument(s)") % name %
 | |
|                          flag.arity);
 | |
|       }
 | |
|       args.push_back(*pos++);
 | |
|     }
 | |
|     flag.handler(std::move(args));
 | |
|     return true;
 | |
|   };
 | |
| 
 | |
|   if (std::string(*pos, 0, 2) == "--") {
 | |
|     auto i = longFlags.find(std::string(*pos, 2));
 | |
|     if (i == longFlags.end()) {
 | |
|       return false;
 | |
|     }
 | |
|     return process("--" + i->first, *i->second);
 | |
|   }
 | |
| 
 | |
|   if (std::string(*pos, 0, 1) == "-" && pos->size() == 2) {
 | |
|     auto c = (*pos)[1];
 | |
|     auto i = shortFlags.find(c);
 | |
|     if (i == shortFlags.end()) {
 | |
|       return false;
 | |
|     }
 | |
|     return process(std::string("-") + c, *i->second);
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool Args::processArgs(const Strings& args, bool finish) {
 | |
|   if (expectedArgs.empty()) {
 | |
|     if (!args.empty()) {
 | |
|       throw UsageError(format("unexpected argument '%1%'") % args.front());
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   auto& exp = expectedArgs.front();
 | |
| 
 | |
|   bool res = false;
 | |
| 
 | |
|   if ((exp.arity == 0 && finish) ||
 | |
|       (exp.arity > 0 && args.size() == exp.arity)) {
 | |
|     std::vector<std::string> ss;
 | |
|     for (auto& s : args) {
 | |
|       ss.push_back(s);
 | |
|     }
 | |
|     exp.handler(std::move(ss));
 | |
|     expectedArgs.pop_front();
 | |
|     res = true;
 | |
|   }
 | |
| 
 | |
|   if (finish && !expectedArgs.empty() && !expectedArgs.front().optional) {
 | |
|     throw UsageError("more arguments are required");
 | |
|   }
 | |
| 
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| Args::FlagMaker& Args::FlagMaker::mkHashTypeFlag(HashType* ht) {
 | |
|   arity(1);
 | |
|   label("type");
 | |
|   description("hash algorithm ('md5', 'sha1', 'sha256', or 'sha512')");
 | |
|   handler([ht](const std::string& s) {
 | |
|     *ht = parseHashType(s);
 | |
|     if (*ht == htUnknown) {
 | |
|       throw UsageError("unknown hash type '%1%'", s);
 | |
|     }
 | |
|   });
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| Strings argvToStrings(int argc, char** argv) {
 | |
|   Strings args;
 | |
|   argc--;
 | |
|   argv++;
 | |
|   while ((argc--) != 0) {
 | |
|     args.push_back(*argv++);
 | |
|   }
 | |
|   return args;
 | |
| }
 | |
| 
 | |
| std::string renderLabels(const Strings& labels) {
 | |
|   std::string res;
 | |
|   for (auto label : labels) {
 | |
|     for (auto& c : label) {
 | |
|       c = std::toupper(c);
 | |
|     }
 | |
|     res += " <" + label + ">";
 | |
|   }
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| void printTable(std::ostream& out, const Table2& table) {
 | |
|   size_t max = 0;
 | |
|   for (auto& row : table) {
 | |
|     max = std::max(max, row.first.size());
 | |
|   }
 | |
|   for (auto& row : table) {
 | |
|     out << "  " << row.first << std::string(max - row.first.size() + 2, ' ')
 | |
|         << row.second << "\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace nix
 |