# Copyright 2024 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//third_party/jinja2/jinja2.gni")
import("//third_party/protobuf/proto_library.gni")

domato_rules = [
  "//third_party/domato/src/rules/attributevalues.txt",
  "//third_party/domato/src/rules/common.txt",
  "//third_party/domato/src/rules/css.txt",
  "//third_party/domato/src/rules/cssproperties.txt",
  "//third_party/domato/src/rules/html.txt",
  "//third_party/domato/src/rules/js.txt",
  "//third_party/domato/src/rules/jshelpers.txt",
  "//third_party/domato/src/rules/mathml.txt",
  "//third_party/domato/src/rules/mathmlattrvalues.txt",
  "//third_party/domato/src/rules/svg.txt",
  "//third_party/domato/src/rules/svgattrvalues.txt",
  "//third_party/domato/src/rules/tagattributes.txt",
]

template("domatolpm") {
  _name = target_name
  _script_target_name = "${_name}_domatolpm_gen"
  _gen_target_name = "${_name}_proto_gen"
  _gen_file_format = "${target_gen_dir}/${_name}"
  _target_gen_dir = target_gen_dir

  # It was determined that above 12 files, the compilation time does not
  # improve anymore.
  _generated_protos = [
    "${_gen_file_format}_sub0.proto",
    "${_gen_file_format}_sub1.proto",
    "${_gen_file_format}_sub2.proto",
    "${_gen_file_format}_sub3.proto",
    "${_gen_file_format}_sub4.proto",
    "${_gen_file_format}_sub5.proto",
    "${_gen_file_format}_sub6.proto",
    "${_gen_file_format}_sub7.proto",
    "${_gen_file_format}_sub8.proto",
    "${_gen_file_format}_sub9.proto",
    "${_gen_file_format}_sub10.proto",
    "${_gen_file_format}_sub11.proto",
  ]
  _generated_cpps = [
    "${_gen_file_format}.cc",
    "${_gen_file_format}.h",
    "${_gen_file_format}_sub0.cc",
    "${_gen_file_format}_sub0.h",
    "${_gen_file_format}_sub1.cc",
    "${_gen_file_format}_sub1.h",
    "${_gen_file_format}_sub2.cc",
    "${_gen_file_format}_sub2.h",
    "${_gen_file_format}_sub3.cc",
    "${_gen_file_format}_sub3.h",
    "${_gen_file_format}_sub4.cc",
    "${_gen_file_format}_sub4.h",
    "${_gen_file_format}_sub5.cc",
    "${_gen_file_format}_sub5.h",
    "${_gen_file_format}_sub6.cc",
    "${_gen_file_format}_sub6.h",
    "${_gen_file_format}_sub7.cc",
    "${_gen_file_format}_sub7.h",
    "${_gen_file_format}_sub8.cc",
    "${_gen_file_format}_sub8.h",
    "${_gen_file_format}_sub9.cc",
    "${_gen_file_format}_sub9.h",
    "${_gen_file_format}_sub10.cc",
    "${_gen_file_format}_sub10.h",
    "${_gen_file_format}_sub11.cc",
    "${_gen_file_format}_sub11.h",
  ]
  action(_script_target_name) {
    testonly = true
    script = "//testing/libfuzzer/research/domatolpm/generator.py"
    args = [
      "-p",
      rebase_path(invoker.grammar_file, root_build_dir),
      "-f",
      rebase_path(_gen_file_format, root_build_dir),
      "-n",
      invoker.grammar_name,
      "-d",
      rebase_path(_target_gen_dir, root_gen_dir),
    ]
    if (defined(invoker.stabilize_grammar) && invoker.stabilize_grammar) {
      args += [ "-s" ]
    }
    inputs = [
      invoker.grammar_file,
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm.cc.tmpl",
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm.h.tmpl",
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm.proto.tmpl",
      "//build/action_helpers.py",
      "//build/gn_helpers.py",
      "//third_party/domato/src/grammar.py",
    ]
    inputs += domato_rules
    inputs += jinja2_sources
    if (defined(invoker.inputs)) {
      inputs += invoker.inputs
    }
    outputs = [ "${_gen_file_format}.proto" ]
    outputs += _generated_protos
    outputs += _generated_cpps
    if (defined(invoker.deps)) {
      deps = invoker.deps
    }
  }
  proto_library(_gen_target_name) {
    testonly = true
    proto_deps = [ ":${_script_target_name}" ]
    sources = [ "${_gen_file_format}.proto" ]
    sources += _generated_protos
    proto_in_dir = "${root_gen_dir}"
    proto_out_dir = "."
    generate_python = false
  }
  static_library(_name) {
    testonly = true
    public_deps = [
      ":${_gen_target_name}",
      ":${_script_target_name}",
      "//base",
    ]
    deps = [ "//testing/libfuzzer/research/domatolpm:domatolpm_context" ]
    sources = _generated_cpps
  }
}

template("domatolpm_fuzzer") {
  _templated_deps = []
  foreach(grammar, invoker.grammars) {
    _grammars = []
    _grammars = string_split(grammar, ":")
    _target_name = _grammars[0]
    _templated_deps += [ ":${_target_name}" ]
    domatolpm(_target_name) {
      grammar_file = _grammars[1]
      grammar_name = _grammars[0]
      if (defined(invoker.deps)) {
        deps = invoker.deps
      }
      if (defined(invoker.stabilize_grammar)) {
        stabilize_grammar = invoker.stabilize_grammar
      }
      if (defined(invoker.inputs)) {
        inputs = invoker.inputs
      }
    }
  }

  _target_gen_dir = target_gen_dir
  _gen_file_format = "${target_gen_dir}/${target_name}"
  _generator_target_name = "${target_name}_template_gen"
  _target_name = target_name
  action(_generator_target_name) {
    testonly = true
    script = "//testing/libfuzzer/research/domatolpm/fuzzer_generator.py"
    deps = _templated_deps
    args = [
      "-p",
      rebase_path(invoker.template_file, root_build_dir),
      "-f",
      rebase_path(_gen_file_format, root_build_dir),
      "-n",
      "${_target_name}",
      "-d",
      rebase_path(_target_gen_dir, root_gen_dir),
    ]
    foreach(grammar, invoker.grammars) {
      _g = []
      _g = string_split(grammar, ":")
      args += [
        "-g",
        "${_g[0]}:${_g[0]}",
      ]
    }
    inputs = [
      invoker.template_file,
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm_fuzzer.h.tmpl",
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm_fuzzer.cc.tmpl",
      "//testing/libfuzzer/research/domatolpm/templates/domatolpm_fuzzer.proto.tmpl",
      "//build/action_helpers.py",
      "//build/gn_helpers.py",
      "//third_party/domato/src/grammar.py",
    ]
    inputs += domato_rules
    inputs += jinja2_sources
    outputs = [
      "${_gen_file_format}.proto",
      "${_gen_file_format}.h",
      "${_gen_file_format}.cc",
    ]
  }

  _proto_gen_target_name = "${target_name}_proto_gen"
  _target_gen_dir = "${target_gen_dir}"
  proto_library(_proto_gen_target_name) {
    testonly = true
    proto_deps = [ ":${_generator_target_name}" ]
    deps = []
    foreach(templated_dep, _templated_deps) {
      deps += [ "${templated_dep}_proto_gen" ]
    }
    sources = [ "${_gen_file_format}.proto" ]
    import_dirs = [ _target_gen_dir ]
    proto_in_dir = "${root_gen_dir}"
    proto_out_dir = "."
    generate_python = false
  }

  static_library(target_name) {
    testonly = true
    public_deps = _templated_deps
    public_deps += [
      ":${_generator_target_name}",
      ":${_proto_gen_target_name}",
      "//base",
    ]
    deps = [ "//testing/libfuzzer/research/domatolpm:domatolpm_context" ]
    sources = [
      "${_gen_file_format}.cc",
      "${_gen_file_format}.h",
    ]
  }
}
