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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
BEGIN {
opt_count = 0;
FIELDS["short"] = 0; # short option
FIELDS["long"] = 0; # long option
FIELDS["arg"] = 0; # option argument
FIELDS["desc"] = 0; # description
FIELDS["func"] = 0; # callback function
}
func PrintShell() {
printf "OPTIONS=(\n# callback short long argument\n"
for (i = 0; i < opt_count; i++)
printf("'%s' '%s' '%s' '%s' '%s'\n",
OPTIONS["func", i], OPTIONS["short", i],
OPTIONS["long", i], OPTIONS["arg", i],
OPTIONS["desc", i]);
printf(")\n");
}
func PrintMan() {
for (i = 0; i < opt_count; i++) {
short = OPTIONS["short", i];
long = OPTIONS["long", i];
arg = OPTIONS["arg", i];
desc = OPTIONS["desc", i];
if (arg)
printf(".TP\n.BI \"-%1s \" %s \", --%s=\" %s",
short, arg, long, arg);
else
printf(".TP\n-%1s, --%s",
short, long);
printf("\n%s\n\n", desc);
}
}
func EmptyEntry(entry) {
#printf("Checking for empty entry at [%d]...\n", entry);
for (type in FIELDS) {
#printf(" Checking for empty field '%s'\n", type);
if (OPTIONS[type, entry])
return 0;
}
return 1;
}
/^\s*#/ { # comment
next;
}
/^\s*$/ { # end of entry
if (!EmptyEntry(opt_count))
opt_count++;
next;
}
/^\s*-/ { # option line
for (i = 1; i <= NF; i++) {
switch ($i) {
case /^-+$/: # ignore fields with only dashes
continue;
case /^--\w[\w-]*/: # long option
sub(/^--/, "", $i);
type = "long";
break;
case /^-\w+/: # short option
sub(/^-/, "", $i);
type = "short";
break;
case /^\w+/: # option argument
type = "arg";
break;
}
OPTIONS[type, opt_count] = $i;
}
}
/^\s*@/ { # function callback line
sub(/^\s*@\s*/, "");
OPTIONS["func", opt_count] = $1;
next;
}
/^\s*"/ {
sub(/^\s*"\s*/, "");
if (OPTIONS["desc", opt_count] !~ /\s$/)
OPTIONS["desc", opt_count] += " ";
OPTIONS["desc", opt_count] = $0;
next;
}
END {
if (!EmptyEntry(opt_count)) opt_count++;
if (!OUTPUT) OUTPUT = "shell";
switch (OUTPUT) {
case "shell":
PrintShell();
break;
case "man":
PrintMan();
break;
default:
printf("Unknown format '%s'", OUTPUT) > "/dev/stderr";
}
}
|