aboutsummaryrefslogtreecommitdiffstats
path: root/tools/get-options.sh
blob: 49d798ce7ba76220b7f50c5f08c3a25890feba15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/bin/bash

# This file is part of util-linux.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# Copyright (C) 2025 Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
TOP_SRCDIR=${TOP_SRCDIR:-../}

# Directories that contain relevant source files for util-linux programs.
src_file_paths="$(grep -rE --include="*.c" --exclude="*test_*"          \
                        --exclude-dir="lib*"                            \
                        --exclude-dir="po*"                             \
                        --exclude-dir="tests"                           \
                        --exclude-dir="tools"                           \
                        --exclude-dir="bash-completion"                 \
                        --exclude-dir=".[a-z]*"                         \
                        --exclude-dir="man-common"                      \
                        --exclude-dir="Documentation"                   \
                        --exclude-dir="build*"                          \
                        -l "getopt_long(_only)?\s*\("                   \
                )"

# We skip these programs because they do not make use of 'struct option longopts[]'
# which is passed to getopt(3) for command line argument parsing.
unsupported_programs='blockdev|fsck|mkfs\.cramfs|pg|renice|whereis'

# In general a program's source file name will be '<program_name>.c', however
# some tools have differing file names. To handle these special cases we build
# a hash table with the program name as the key and the actual source file name
# as the value, the latter will ultimately be passed to find_prog_src().
typeset -A canonical_src_prefix
canonical_src_prefix=( \
        [su]="su-common"
)

function find_prog_src() {
        local prog
        prog="$1"

        for p in ${src_file_paths}; do
                if [[ "${p##*/}" =~ ^"${prog}".c$ ]]; then
                        echo "${TOP_SRCDIR}/${p}"
                        break
                fi
        done
}

function extract_long_opts() {
        local src_path
        src_path="$1"

        awk -F ',' 'BEGIN { x = 0 }; \
                /struct[[:space:]]*option[[:space:]]*.*[[:space:]]*\[\][[:space:]]*=[[:space:]]*(\{)?/ { x = 1 } \
                x && ! /.*\/\*.*(deprecated|COMPLETION:no).*\*\/.*/ {  print $1 } \
                /\};/ { x = 0 }' "${src_path}"  \
                | grep -Eo '".*"'               \
                | tr -d '"'                     \
                | sort                          \
                | awk '{ printf "--%s\n", $0 }' \
                | grep -v '^--_.*$'
}

function main() {
        local progname
        progname="$1"

        if [[ "$progname" =~ $unsupported_programs ]]; then
                echo "ENOTSUP"
                return 0
        fi

        # Handle special programs that have unusual source file names
        if [ -n "${canonical_src_prefix[$progname]+exists}" ]; then
                progname="${canonical_src_prefix[$progname]}"
        fi

        src_path="$(find_prog_src "$progname")"
        if [ -z "$src_path" ]; then
                return 1
        fi

        extract_long_opts "$src_path"

        return 0
}

main "$@"