Home | History | Annotate | Download | only in profile_reset
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // A simple command-line compiler for JTL (JSON Traversal Language).
      6 //
      7 // Translates rules from a text-based, human-readable format to an easy-to-parse
      8 // byte-code format, which then can be interpreted by JtlInterpreter.
      9 //
     10 // Example usage:
     11 //   jtl_compiler --input=blah.txt --hash-seed="foobar" --output=blah.dat
     12 
     13 #include <iostream>
     14 #include <string>
     15 
     16 #include "base/command_line.h"
     17 #include "base/file_util.h"
     18 #include "base/files/file_path.h"
     19 #include "chrome/tools/profile_reset/jtl_compiler.h"
     20 
     21 namespace {
     22 
     23 // Command-line argument name: path to the input text-based JTL source code.
     24 const char kInputPath[] = "input";
     25 
     26 // Command-line argument name: path to the output byte-code.
     27 const char kOutputPath[] = "output";
     28 
     29 // Command-line argument name: the hash seed to use.
     30 const char kHashSeed[] = "hash-seed";
     31 
     32 // Error codes.
     33 const char kMismatchedDoubleQuotes[] = "Mismatched double-quotes before EOL.";
     34 const char kParsingError[] = "Parsing error. Input is ill-formed.";
     35 const char kArgumentCountError[] = "Wrong number of arguments for operation.";
     36 const char kArgumentTypeError[] = "Wrong argument type(s) for operation.";
     37 const char kArgumentValueError[] = "Wrong argument value(s) for operation.";
     38 const char kUnknownOperationError[] = "No operation by this name.";
     39 const char kUnknownError[] = "Unknown error.";
     40 
     41 const char* ResolveErrorCode(JtlCompiler::CompileError::ErrorCode code) {
     42   switch (code) {
     43     case JtlCompiler::CompileError::MISMATCHED_DOUBLE_QUOTES:
     44       return kMismatchedDoubleQuotes;
     45     case JtlCompiler::CompileError::PARSING_ERROR:
     46       return kParsingError;
     47     case JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT:
     48       return kArgumentCountError;
     49     case JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE:
     50       return kArgumentTypeError;
     51     case JtlCompiler::CompileError::INVALID_ARGUMENT_VALUE:
     52       return kArgumentValueError;
     53     case JtlCompiler::CompileError::INVALID_OPERATION_NAME:
     54       return kUnknownOperationError;
     55     default:
     56       return kUnknownError;
     57   }
     58 }
     59 
     60 }  // namespace
     61 
     62 int main(int argc, char* argv[]) {
     63   CommandLine::Init(argc, argv);
     64   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
     65   if (!cmd_line->HasSwitch(kInputPath) || !cmd_line->HasSwitch(kHashSeed) ||
     66       !cmd_line->HasSwitch(kOutputPath)) {
     67     std::cerr << "Usage: " << argv[0] << " <required switches>" << std::endl;
     68     std::cerr << "\nRequired switches are:" << std::endl;
     69     std::cerr << "  --" << kInputPath << "=<file>"
     70               << "\t\tPath to the input text-based JTL source code."
     71               << std::endl;
     72     std::cerr << "  --" << kOutputPath << "=<file>"
     73               << "\t\tPath to the output byte-code." << std::endl;
     74     std::cerr << "  --" << kHashSeed << "=<value>"
     75               << "\t\tThe hash seed to use." << std::endl;
     76     return -1;
     77   }
     78 
     79   base::FilePath source_code_path =
     80       MakeAbsoluteFilePath(cmd_line->GetSwitchValuePath(kInputPath));
     81   std::string source_code;
     82   if (!base::ReadFileToString(source_code_path, &source_code)) {
     83     std::cerr << "ERROR: Cannot read input file." << std::endl;
     84     return -3;
     85   }
     86 
     87   std::string bytecode;
     88   JtlCompiler::CompileError error;
     89   std::string hash_seed = cmd_line->GetSwitchValueASCII(kHashSeed);
     90   if (!JtlCompiler::Compile(source_code, hash_seed, &bytecode, &error)) {
     91     std::cerr << "COMPILE ERROR: " << ResolveErrorCode(error.error_code)
     92               << std::endl;
     93     std::cerr << "  Line number: " << (error.line_number + 1) << std::endl;
     94     std::cerr << "  Context: " << (error.context.size() > 63
     95                                        ? error.context.substr(0, 60) + "..."
     96                                        : error.context) << std::endl;
     97     return -2;
     98   }
     99 
    100   base::FilePath bytecode_path =
    101       MakeAbsoluteFilePath(cmd_line->GetSwitchValuePath(kOutputPath));
    102   int bytes_written =
    103       base::WriteFile(cmd_line->GetSwitchValuePath(kOutputPath),
    104                            bytecode.data(),
    105                            static_cast<int>(bytecode.size()));
    106   if (bytes_written != static_cast<int>(bytecode.size())) {
    107     std::cerr << "ERROR: Cannot write output file." << std::endl;
    108     return -3;
    109   }
    110 
    111   return 0;
    112 }
    113