3 # Patcher script to import getopt.c from Gnulib in order to remove
4 # bits and make it directly usable as a fallback getopt_long(_only)
5 # implementation in programs.
7 # Copyright © 2024 Nick Bowler
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
22 # Exercising section 3 of the LGPLv2.1 to the modified library:
24 # You may opt to apply the terms of the ordinary GNU General Public
25 # License instead of this License to a given copy of the Library. To
26 # do this, you must alter all the notices that refer to this License,
27 # so that they refer to the ordinary GNU General Public License, version 2,
28 # instead of this License. (If a newer version than version 2 of the
29 # ordinary GNU General Public License has appeared, then you can specify
30 # that version instead if you wish.) Do not make any other change in
33 # "GNU Lesser General Public License" -> "GNU General Public License"
34 sub(/Lesser General
/, "General");
36 # "version 2.1 of the License" -> "version 3 of the License"
37 sub(/version
2[.
]1/, "version 3");
40 # Remove all conditionally compiled blocks
41 BEGIN { cond_depth =
0; }
42 /^
#[\t ]*if/ { cond_depth++; }
43 /^
#[\t ]*endif/ { cond_depth--; next; }
44 cond_depth
> 0 { next; }
46 # Replace references to getopt_data with direct variable names
47 { gsub(/d
->__
/, ""); gsub(/d
->opt
/, "opt"); }
49 # Rename stuff out of the implementation-reserved namespace
50 { gsub(/_getopt_internal_r
/, "gnu_getopt"); }
51 { gsub(/_getopt_initialize
/, "initialize"); }
53 # Remove comment and macro about removed plain "getopt"
54 /LSB
-compliant getopt
/ { while (!
/[*][/]/) getline; next; }
55 /^
#[\t ]*define +GETOPT_ENTRY/ { while (/\\$/) getline; next; }
57 # Avoid further touches to block comments
58 BEGIN { first_comment = in_comment =
0; }
59 /^
[\t ]*[/][*]/ { in_comment =
1; }
62 if (first_comment ==
0) first_comment =
1;
66 print deferred_blank
(last_line = $
0);
71 # Add our stuff right after the copyright notice
75 date_cmd=
"date +%Y-%m-%d";
76 date_cmd
| getline date
;
80 print " * This file has been modified from its original version,";
81 if (date
) date =
" on " date
;
82 print " * postprocessed by import-gnu-getopt.awk" date
;
86 print "\n#if HAVE_CONFIG_H";
87 print "#\tinclude <config.h>";
90 print "#include <stdio.h>";
91 print "#include <stdlib.h>";
92 print "#include <string.h>";
93 print "#include \"gnu_getopt.h\"\n";
95 print "#if ENABLE_NLS"
96 print "#\tinclude <libintl.h>"
98 print "#\tdefine gettext(x) (x)";
103 # Remove all includes from the input.
104 /^
#[\t ]*include/ { next; }
106 # Remove linter nonsense
107 { gsub(/_GL_UNUSED
*/, ""); }
110 { gsub(/(__libc_use_alloca
|alloca
) *[(][^
)]*[)]/, "0"); }
112 # Convert _() to a direct gettext call
113 { gsub(/_
[(]"/, "gettext
(\""); }
115 # Remove stdio locking
116 /f(un)?lockfile/ { next; }
118 # Replace global getopt_data struct with separate global variables ...
119 /^static.*getopt_data/ {
120 $0 = "static int first_nonopt
, last_nonopt
;\n" \
121 "static char
*nextchar
;\n" \
122 "static unsigned char ordering
, initialized
;\n" \
123 "enum
{ REQUIRE_ORDER
, PERMUTE
, RETURN_IN_ORDER
};";
126 # ... and remove parameter declarations of it everywhere ...
127 { sub(/, *struct +_getopt_data *[*] *d/, ""); }
128 /^[\t ]*struct +_getopt_data *[*] *d,/ {
129 sub(/struct +_getopt_data *[*] *d, */, "");
132 # ... and remove it from function calls
133 { gsub(/, *d *,/, ","); gsub(/, *d *[)]/, ")"); }
135 # Also remove posixly_correct parameter from functions
137 sub(/, *int +posixly_correct *[)]/, ")");
138 sub(/int +posixly_correct *[)]/, "int unused
)");
139 gsub(/posixly_correct/, "0");
142 # Remove _getopt_internal function completely
143 BEGIN { func_delete = 0; func_block = 0; func_tmp = ""; }
144 /^int$/ { func_tmp = $0; next; }
146 if ($1 == "_getopt_internal
") {
149 $0 = func_tmp ORS $0;
155 if ((func_block += gsub(/{/, "{")) > 0) {
156 if ((func_block -= gsub(/}/, "}")) == 0) {
163 # For the tests, move optind/opterr assignments into do_getopt_long_(only), as
164 # all callers explicitly set these to 1 and 0, respectivly, prior to the call.
165 # In addition to reducing the complexity of the test program, this also works
166 # around a code generation bug in old versions of MIPSpro C.
167 BEGIN { in_wrapper = 0; in_test = 0; }
168 /^do_getopt_long/ { in_wrapper = 1; }
170 $0 = $0 "\n optind =
1, opterr =
0;";
174 # Drop no longer needed optind/opterr assignments
175 in_test && (/optind *= *1/ || /opterr *= *0/) { next; }
176 /^test_getopt/ { in_test = 1; }
177 in_test && /^}/ { in_test = 0; }
179 # Consolidate redundant declarations in the test functions
180 in_test == 2 && /char *[*]argv\[/ { next; }
181 in_test == 2 && /int *c;/ { next; }
182 in_test == 1 && /{/ {
183 $0 = $0 "\n const char
*argv[20];\n int c
;";
187 # Remove consecutive blank lines which may be generated by the above
188 BEGIN { last_line = ""; deferred_blank = ""; }
190 empty = sub(/^[\f\t ]*$/, "")
192 if (!empty && deferred_blank) {
193 print (deferred_blank = "");
196 if (!empty || last_line != "") {
198 deferred_blank = ORS;