#!/bin/sh
# -*- tab-width: 4 -*- ;; Emacs
# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM
############################################################ LICENSE
#
# Copyright (c) 2026 Devin Teske <dteske@FreeBSD.org>
#
# SPDX-License-Identifier: BSD-2-Clause
#
############################################################ IDENT(1)
#
# $Title: Generate priv.d from <sys/priv.h> for libdtrace(3) $
# $Copyright: 2026 Devin Teske. All rights reserved. $
#
############################################################ GLOBALS

VERSION='$Version: 1.0 $'

pgm="${0##*/}" # Program basename

#
# Global exit status
#
SUCCESS=0
FAILURE=1

#
# Command-line options
#
OUTPUT_FILE=	# -o file

#
# Miscellaneous
#
PRIV_H=

############################################################ FUNCTIONS

usage()
{
	local fmt="$1"
	local optfmt="\t%-5s %s\n"

	exec >&2
	if [ "$fmt" ]; then
		shift 1 # fmt
		printf "%s: $fmt\n" "$pgm" "$@"
	fi
	printf "Usage: %s [-hv] [-o file] priv.h\n" "$pgm"
	printf "Options:\n"
	printf "$optfmt" "-h" "Print this usage statment and exit."
	printf "$optfmt" "-o file" "Write to output file instead of stdout."
	printf "$optfmt" "-v" "Print version information and exit."
	exit $FAILURE
}

############################################################ MAIN

#
# Process command-line options
#
while getopts ho:v flag; do
	case "$flag" in
	o) OUTPUT_FILE="$OPTARG" ;;
	v) VERSION="${VERSION#*: }"
		echo "${VERSION% $}"
		exit $SUCCESS ;;
	*) usage # NOTREACHED
	esac
done
shift $(( $OPTIND - 1 ))

#
# Check command-line arguments
#
[ $# -gt 0 ] || usage "Too few arguments" # NOTREACHED
[ $# -eq 1 ] || usage "Too many arguments" # NOTREACHED
[ "$1" ] || usage "Missing priv.h argument" # NOTREACHED
[ -e "$1" ] || usage "%s: No such file or directory" "$1" # NOTREACHED

#
# Generate priv.d contents from priv.h input
#
PRIV_H="$1"
exec 9<<PRIV_D_EOF
/*-
 * Copyright (c) 2026 Devin Teske <dteske@FreeBSD.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

/*
 * Map priv(9) privilege values to their symbolic names.
 * NB: Mechanically generated from <sys/priv.h> -- keep in-sync.
 * NB: Generated by /usr/src/cddl/lib/libdtrace/$pgm
 */

#pragma D binding "1.13" priv_string
inline string priv_string[int priv] =
$( awk '
	/^#define[[:space:]]+PRIV_[A-Z0-9_]+[[:space:]]+[0-9]+/ {
		for (i = 0; ++i <= NF; ) if ($i ~ /define/) break
		name = $++i
		value = $++i
		printf "\tpriv == %s ?\t\t\"%s\" :\n", value, name
	}' "$PRIV_H"
)
	strjoin("PRIV_UNKNOWN#", lltostr(priv));
PRIV_D_EOF

#
# Output contents
#
[ ! "$OUTPUT_FILE" ] || exec > "$OUTPUT_FILE"
cat <&9

################################################################################
# END
################################################################################
