#!/usr/bin/env ruby
# frozen_string_literal: true

# gentable: generate a lookup table of syscall names -> numbers

require "open3"

PLATFORM = ARGV.shift || `uname -s`.chomp!.downcase!

abort "Barf: Unknown platform: #{PLATFORM}" unless %w[linux freebsd].include? PLATFORM

SYSCALL_H_CANDIDATES = %w[
  /usr/include/sys/syscall.h
  /usr/include/x86_64-linux-gnu/sys/syscall.h
].freeze

SYSCALL_H = SYSCALL_H_CANDIDATES.find { |f| File.exist? f }

OUTPUT_NAME = File.expand_path "table.gen.c", __dir__

def hai(msg)
  STDERR.puts "[gentable] #{msg}"
end

abort "Barf: no sys/syscall.h" unless SYSCALL_H

processed, status = Open3.capture2("cc -dD -E -", stdin_data: File.read(SYSCALL_H))

abort "Barf: Preprocess failed" unless status.success?

table = if PLATFORM == "linux"
          lines = processed.lines.select { |l| l.match?(/^#define __NR_/) }.map(&:chomp)
          lines.map do |line|
            const, number = line.split[1..2]

            [const[5..-1], number]
          end.to_h
        elsif PLATFORM == "freebsd"
          lines = processed.lines.select { |l| l.match?(/^#define SYS_/) }.map(&:chomp)
          lines.map do |line|
            const, number = line.split[1..2]

            [const[4..-1], number]
          end.to_h
        end

hai "building lookup table with #{table.size} entries"

File.open(OUTPUT_NAME, "w") do |file|
  file.puts <<~PREAMBLE
    /* WARNING!
     * This file was generated by KRF's gentable.
     * Do not edit it by hand.
     */

    #include <stdlib.h>

    #include "krfctl.h"
  PREAMBLE

  file.puts "syscall_lookup_t syscall_lookup_table[] = {"

  table.each do |name, number|
    next if PLATFORM == "freebsd" && name == "MAXSYSCALL"

    file.puts %({ "#{name}", "#{number}" },)
  end

  file.puts "{ NULL, 0 },"
  file.puts "};"
end
