#!/bin/sh
#
# Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

#
# Usage: ./util/ctags.sh [...arguments for ctags...]
#
# This script runs ctags twice. In the first pass, ctags extract macro
# definitions. readtags that is part of Universal Ctags converts them
# to ctags options. In the second pass, ctags reads the options and
# extracts language objects with expanding the macros.
#
# Universal Ctags 6.0.0 or higher is assumed.
#
: ${CTAGS=ctags}
: ${READTAGS=readtags}

if ! type "${CTAGS}" > /dev/null; then
    echo "${CTAGS}: not found" 1>&2
    exit 1
fi

if [ $# -eq 0 ]; then
    set -- -R
fi

if ! "${CTAGS}" --version | grep -q "Universal Ctags"; then
    "${CTAGS}" "$@"
    exit $?
fi

if "${CTAGS}" --version | grep -q "Universal Ctags 5.*"; then
    "${CTAGS}" "$@"
    exit $?
fi

if ! type "${READTAGS}" > /dev/null 2>&1; then
    echo "WARNING: ${READTAGS}: not found" 1>&2
    echo "WARNING: \"tagging after macro expanding\" doesn't work" 1>&2
    "${CTAGS}" "$@"
    exit $?
fi

if ! [ -d ./.ctags.d ]; then
    echo "No ./.ctags.d directory" 1>&2
    exit 1
fi

{
    # At the first pass, ctags should not be affected by personal
    # configuration files. So --options=NONE is passed.
    #
    # However, if the option is passed, ctags doesn't load the project
    # default configuration files under $project/.ctags.d. So we load
    # the project default configuration files, add-dir.ctags and
    # exclude.ctags, explicitly.
    #
    # openssl-stage1 contains a configuration file specialized to
    # extract macro definitions. It should not be used in normal ctags
    # usage.
    $CTAGS --quiet --options=NONE \
	   --options=./.ctags.d/add-dir.ctags \
	   --options=./.ctags.d/exclude.ctags \
	   --options=openssl-stage1
} | {
    macros=.ctags.d/openssl-stage2/50macro-definitons.ctags
    cat > "$macros" <<EOF
#
# This file is automatically generated by $0.
# DON'T EDIT THIS FILE MANUALLY
#
EOF
    # Extract macro definitions and convert them to ctags options.
    $READTAGS --tag-file - \
	      -Q '(and (eq? $kind "d") ($ "macrodef"))'  \
	      -F '(list "-D" $name $signature "=" ($ "macrodef") #t)' \
	      -l >> "$macros" &&
	# At the second path, ctags extract tags with expanding macros stored in
	# 50macro-definitons.ctags.
	$CTAGS --options=openssl-stage2 \
	       "$@"
}
