POSIX.1 National Language Support API for MinGW
Revision | 8fd865b89fd0504dfe5a5199e2be56155177f0b9 (tree) |
---|---|
Zeit | 2008-01-09 04:51:59 |
Autor | Keith Marshall <keithmarshall@user...> |
Commiter | Keith Marshall |
Add -help' and -version' options for gencat'.
@@ -1,3 +1,58 @@ | ||
1 | +2008-01-08 Keith Marshall <keithmarshall@users.sourceforge.net> | |
2 | + | |
3 | + Add `-help' and `-version' options for `gencat'. | |
4 | + | |
5 | + * repl/getopt.c: New file; it provides a replacement for the | |
6 | + `libmingwex.a' implementation of the `getopt' object module, with... | |
7 | + (getopt_long_only): New function; implement it. | |
8 | + | |
9 | + * repl/include/getopt.h: New file; it provides a replacement header | |
10 | + for use with the above replacement getopt.c implementation. | |
11 | + | |
12 | + * gencat.c: Add more comments; update copyright notice for new year. | |
13 | + (PROGRAM_IDENTITY): New manifest definition. | |
14 | + (AUTHOR_IDENTITY, AUTHOR_ATTRIBUTION): Ditto. | |
15 | + (COPYRIGHT_YEARS, COPYRIGHT_HOLDER, COPYRIGHT_NOTICE): Ditto. | |
16 | + (stdarg.h, getopt.h): Include. | |
17 | + (banner_printf): New static function. | |
18 | + (main): Add `options' defining structure; filter `argv' through it, | |
19 | + using `getopt_long_only' function. | |
20 | + | |
21 | + * include/gcmsgs.h: Update copyright notice for new year. | |
22 | + Renumber existing message sets, making initial space to insert... | |
23 | + (MSG_PROGRAM_BANNER): New message definition; allocate exclusively to | |
24 | + message set #1, for display by both `-help' and `-version' options. | |
25 | + (MSG_COPYRIGHT_NOTICE): New message definition; allocate exclusively | |
26 | + to message set #2, for display by `-version' option. | |
27 | + (MSG_GENCAT_SYNOPSIS): New message definition; allocate exclusively to | |
28 | + message set #3, for display by `-help' option. | |
29 | + Add additional comments; document message set allocations. | |
30 | + | |
31 | + * gendefs.awk (MULTILINE): New control variable; use it to implement | |
32 | + handling for multiline message definitions. | |
33 | + | |
34 | + * Makefile.in (DEV_SCRIPTS): Renamed again, to... | |
35 | + (DISTDEV_SCRIPTS): ...this; it specifies the distributable scripts. | |
36 | + (EXECDEV_SCRIPTS): Define; it specifies executable variants of these. | |
37 | + (all-targets): Include EXECDEV_SCRIPTS, to ensure they are built. | |
38 | + (install-scripts): Ditto, to install them. | |
39 | + (AWK_INTERPRETER): New autoconf substitution; use it to define a | |
40 | + generic pattern rule, for generating EXECDEV_SCRIPTS from awk scripts | |
41 | + specified in DISTDEV_SCRIPTS. | |
42 | + | |
43 | + * aclocal.m4: Add copyright notice, and other macro specific comments. | |
44 | + (GENCAT_AC_FUNC_GETOPT_LONG_ONLY): New macro; it checks for presence | |
45 | + of the getopt_long_only() function, in the standard C libraries. | |
46 | + (GENCAT_AC_OBJECTS_ADD_GETOPT): New macro; it is invoked if needed, by | |
47 | + GENCAT_AC_FUNC_GETOPT_LONG_ONLY, to schedule building of a replacement | |
48 | + getopt function module, providing getopt_long_only(). | |
49 | + | |
50 | + * configure.ac: Update copyright notice, for new year. | |
51 | + (AWK_INTERPRETER): New AC_SUBST variable; defined by AC_PATH_PROG. | |
52 | + (GENCAT_AC_FUNC_GETOPT_LONG_ONLY): Invoke. | |
53 | + | |
54 | + * configure: Regenerated. | |
55 | + | |
1 | 56 | 2008-01-01 Keith Marshall <keithmarshall@users.sourceforge.net> |
2 | 57 | |
3 | 58 | Establish package structure for distribution. |
@@ -94,7 +94,7 @@ GENCAT_SOURCES = gencat.c mcload.c mcsource.c mciconv.c mcmerge.c mcutfsig.c | ||
94 | 94 | GENCAT_OBJECTS = @GENCAT_OBJECTS@ |
95 | 95 | |
96 | 96 | OTHER_SOURCES = $(DISTDOC_SOURCES) mkinstalldirs install-sh $(MISC_SOURCES) |
97 | -MISC_SOURCES = $(CONFIG_HEADERS) $(CONFIG_SOURCES) $(DEV_SCRIPTS) | |
97 | +MISC_SOURCES = $(CONFIG_HEADERS) $(CONFIG_SOURCES) $(DISTDEV_SCRIPTS) | |
98 | 98 | |
99 | 99 | DISTDOC_SOURCES = ChangeLog COPYING FDL README |
100 | 100 | MANPAGE_SOURCES = catopen.man catgets.man catclose.man gencat.man |
@@ -133,7 +133,13 @@ BUILD_LIBS = libcatgets.a | ||
133 | 133 | BUILD_DLLS = catgets$(DLLVERSION).dll |
134 | 134 | DLLVERSION = @DLLVERSION@ |
135 | 135 | |
136 | -DEV_SCRIPTS = gendefs.awk | |
136 | +DISTDEV_SCRIPTS = gendefs.awk | |
137 | + | |
138 | +# DISTDEV_SCRIPTS may not be directly runnable... | |
139 | +# EXECDEV_SCRIPTS derives from them, creating variants with appropriate | |
140 | +# shebang entries, making them directly executable from a command line. | |
141 | +# | |
142 | +EXECDEV_SCRIPTS = gendefs | |
137 | 143 | |
138 | 144 | # Generic rule, replacing the built-in default, to create an object file |
139 | 145 | # from a C source file... |
@@ -158,8 +164,15 @@ AUTOGENERATED = Automatically generated from $<; do not edit! | ||
158 | 164 | %.h: repl/include/%.h |
159 | 165 | $(LN_S) $< $@ |
160 | 166 | |
167 | +# Generic rule to make a runnable (shebanged) script, | |
168 | +# from a non-runnable awk program script. | |
169 | +# | |
170 | +%: %.awk | |
171 | + sed '1s,!.*,! @AWK_INTERPRETER@ -f,' $< > $@ | |
172 | + chmod 755 $@ | |
173 | + | |
161 | 174 | all-dll = @MAKE_DLL@ |
162 | -all-targets = @MAKE_TARGETS@ | |
175 | +all-targets = $(EXECDEV_SCRIPTS) @MAKE_TARGETS@ | |
163 | 176 | |
164 | 177 | all: $(all-targets) |
165 | 178 |
@@ -227,7 +240,7 @@ install-bin-progs: $(BUILD_PROGS) | ||
227 | 240 | $(INSTALL_PROGRAM) $$prog ${bindir}/$(tool_prefix)$$progname; \ |
228 | 241 | done |
229 | 242 | |
230 | -install-scripts: $(DEV_SCRIPTS) | |
243 | +install-scripts: $(EXECDEV_SCRIPTS) | |
231 | 244 | $(mkinstalldirs) --require ${prefix} ${scriptdir} |
232 | 245 | for script in $^; do \ |
233 | 246 | prog=`IFS='\\/'; set x $$script; eval echo '$$'$$#`; \ |
@@ -361,4 +374,4 @@ distclean: distclean-cross-hosted clean | ||
361 | 374 | distclean-cross-hosted: FORCE |
362 | 375 | rm -rf cross-build |
363 | 376 | |
364 | -# $RCSfile$Revision: 1.5 $: end of file | |
377 | +# $RCSfile$Revision: 1.6 $: end of file |
@@ -1,5 +1,16 @@ | ||
1 | 1 | # aclocal.m4 -*- Autoconf -*- vim: filetype=config |
2 | 2 | # |
3 | +# $Id$ | |
4 | +# | |
5 | +# Copyright (C) 2006, 2007, 2008, MinGW Project | |
6 | +# Written by Keith Marshall <keithmarshall@users.sourceforge.net> | |
7 | +# | |
8 | +# This is aclocal.m4 for the MinGW `catgets' package. | |
9 | +# | |
10 | +# This is free software; it is provided `as is', in the hope that it may | |
11 | +# be useful, but WITHOUT WARRANTY OF ANY KIND, not even an implied warranty | |
12 | +# of MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. | |
13 | +# | |
3 | 14 | m4_include([m4/pkgid.m4]) |
4 | 15 | m4_include([m4/iconv.m4]) |
5 | 16 |
@@ -208,39 +219,106 @@ AC_DEFUN([CATGETS_AC_CONFIG_TARGET], | ||
208 | 219 | fi[]dnl |
209 | 220 | ])# CATGETS_AC_CONFIG_TARGET |
210 | 221 | |
222 | +# GENCAT_AC_OBJECTS_INIT | |
223 | +# ---------------------- | |
224 | +# Initialise the list of object files to be compiled, | |
225 | +# as prerequisites for building the `gencat' executable. | |
226 | +# | |
211 | 227 | AC_DEFUN([GENCAT_AC_OBJECTS_INIT], |
212 | 228 | [GENCAT_OBJECTS=${GENCAT_OBJECTS-'gencat.$(OBJEXT)'} |
213 | 229 | AC_SUBST([GENCAT_OBJECTS])dnl |
214 | 230 | ])# GENCAT_AC_OBJECTS_INIT |
215 | 231 | |
232 | +# GENCAT_AC_OBJECTS_ADD( OBJECT_FILE_NAME ) | |
233 | +# ----------------------------------------- | |
234 | +# Add OBJECT_FILE_NAME to the list of object files to be compiled, | |
235 | +# as prerequisites for building the `gencat' executable. | |
236 | +# | |
216 | 237 | AC_DEFUN([GENCAT_AC_OBJECTS_ADD], |
217 | 238 | [AC_REQUIRE([GENCAT_AC_OBJECTS_INIT])dnl |
218 | 239 | GENCAT_OBJECTS=${GENCAT_OBJECTS}' $1.$(OBJEXT)'dnl |
219 | 240 | ])# GENCAT_AC_OBJECTS_ADD |
220 | 241 | |
242 | +# GENCAT_AC_FUNC_BASENAME | |
243 | +# ----------------------- | |
244 | +# Check if the standard C library provides the `basename' function; | |
245 | +# if not, add `basename.$(OBJEXT)' to the list of prerequisite objects | |
246 | +# to be compiled, to ensure that a replacement is made available from | |
247 | +# package local sources. | |
248 | +# | |
221 | 249 | AC_DEFUN([GENCAT_AC_FUNC_BASENAME], |
222 | 250 | [AC_REQUIRE([GENCAT_AC_OBJECTS_INIT])dnl |
223 | 251 | AC_CHECK_FUNCS([basename],[],GENCAT_AC_OBJECTS_ADD([basename]))dnl |
224 | 252 | ])# GENCAT_AC_FUNC_BASENAME |
225 | 253 | |
254 | +# GENCAT_AC_FUNC_MKSTEMP | |
255 | +# ---------------------- | |
256 | +# Check if the standard C library provides the `mkstemp' function; | |
257 | +# if not, add `mkstemp.$(OBJEXT)' to the list of prerequisite objects | |
258 | +# to be compiled, to ensure that a replacement is made available from | |
259 | +# package local sources. | |
260 | +# | |
226 | 261 | AC_DEFUN([GENCAT_AC_FUNC_MKSTEMP], |
227 | 262 | [AC_REQUIRE([GENCAT_AC_OBJECTS_INIT])dnl |
228 | 263 | AC_CHECK_FUNCS([mkstemp],[],GENCAT_AC_OBJECTS_ADD([mkstemp]))dnl |
229 | 264 | ])# GENCAT_AC_FUNC_MKSTEMP |
230 | 265 | |
266 | +# GENCAT_AC_FUNC_GETOPT_LONG_ONLY | |
267 | +# ------------------------------- | |
268 | +# Check if the standard C library provides the `getopt_long_only' | |
269 | +# function; if not, add `getopt.$(OBJEXT)' to the list of prerequisite | |
270 | +# objects to be compiled, to ensure that a replacement is made available | |
271 | +# from package local sources. | |
272 | +# | |
273 | +AC_DEFUN([GENCAT_AC_FUNC_GETOPT_LONG_ONLY], | |
274 | +[AC_REQUIRE([GENCAT_AC_OBJECTS_INIT])dnl | |
275 | + AC_CHECK_FUNCS([getopt_long_only],[],GENCAT_AC_OBJECTS_ADD_GETOPT)dnl | |
276 | +])# GENCAT_AC_FUNC_GETOPT_LONG_ONLY | |
277 | + | |
278 | +# GENCAT_AC_OBJECTS_ADD_GETOPT | |
279 | +# ---------------------------- | |
280 | +# Helper macro invoked by GENCAT_AC_FUNC_GETOPT_LONG_ONLY, | |
281 | +# to add `getopt.$(OBJECT)' to the list of prerequisite objects | |
282 | +# to be compiled; it also ensures that a compatible version of | |
283 | +# `getopt.h' is used, by adding a compatible package local | |
284 | +# version to the LOCAL_HEADERS list. | |
285 | +# | |
286 | +AC_DEFUN([GENCAT_AC_OBJECTS_ADD_GETOPT], | |
287 | +[AC_SUBST([LOCAL_HEADERS],["getopt.h ${LOCAL_HEADERS}"]) | |
288 | + GENCAT_AC_OBJECTS_ADD([getopt])dnl | |
289 | +])# GENCAT_AC_OBJECTS_ADD_GETOPT | |
290 | + | |
291 | +# GENCAT_AC_FUNC_LANGINFO | |
292 | +# ----------------------- | |
293 | +# Check if the standard C library provides the `nl_langinfo' function; | |
294 | +# if not, add `langinfo.$(OBJEXT)' to the list of prerequisite objects | |
295 | +# to be compiled, to ensure that a replacement is made available from | |
296 | +# package local sources. | |
297 | +# | |
231 | 298 | AC_DEFUN([GENCAT_AC_FUNC_NL_LANGINFO], |
232 | 299 | [AC_REQUIRE([GENCAT_AC_OBJECTS_INIT])dnl |
233 | 300 | AC_CHECK_FUNCS([nl_langinfo],[],GENCAT_AC_OBJECTS_ADD([langinfo]))dnl |
234 | 301 | ])# GENCAT_AC_FUNC_NL_LANGINFO |
235 | 302 | |
303 | +# CATGETS_AC_CONFIG_VERSION | |
304 | +# ------------------------- | |
305 | +# Propagate the `catgets' version number into object code, | |
306 | +# via manifest definitions in `config.h'. | |
307 | +# | |
236 | 308 | AC_DEFUN([CATGETS_AC_CONFIG_VERSION], |
237 | 309 | [CATGETS_AC_CONFIG_VERSION_DEFINE([CATGETS_VERSION_MAJOR],[major],[2])dnl |
238 | 310 | CATGETS_AC_CONFIG_VERSION_DEFINE([CATGETS_VERSION_MINOR],[minor],[3])dnl |
239 | 311 | ])# CATGETS_AC_CONFIG_VERSION |
240 | 312 | |
313 | +# CATGETS_AC_CONFIG_VERSION_DEFINE | |
314 | +# -------------------------------- | |
315 | +# Helper macro invoked by CATGETS_AC_CONFIG_VERSION, | |
316 | +# to place manifest definitions of the `catgets' major and minor | |
317 | +# version numbers into `config.h'. | |
318 | +# | |
241 | 319 | AC_DEFUN([CATGETS_AC_CONFIG_VERSION_DEFINE], |
242 | 320 | [AC_DEFINE_UNQUOTED([$1],[`IFS=.;set x $PACKAGE_VERSION;echo ${$3}`], |
243 | 321 | [Define numerically to the catgets $2 version number])dnl |
244 | 322 | ])# CATGETS_AC_CONFIG_VERSION_DEFINE |
245 | 323 | |
246 | -# $RCSfile$Revision: 1.2 $: end of file | |
324 | +# $RCSfile$Revision: 1.3 $: end of file |
@@ -310,7 +310,7 @@ ac_includes_default="\ | ||
310 | 310 | # include <unistd.h> |
311 | 311 | #endif" |
312 | 312 | |
313 | -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAKE_TARGETS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S AR ac_ct_AR INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MAKE_DLL DLLVERSION canonical_prefix HOST_PATH_SEPARATOR REPLACEMENT_HEADERS CPP EGREP LOCAL_HEADERS GENCAT_OBJECTS INCICONV LIBICONV LIBOBJS LTLIBOBJS' | |
313 | +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAKE_TARGETS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S AR ac_ct_AR AWK_INTERPRETER INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MAKE_DLL DLLVERSION canonical_prefix HOST_PATH_SEPARATOR REPLACEMENT_HEADERS CPP EGREP LOCAL_HEADERS GENCAT_OBJECTS INCICONV LIBICONV LIBOBJS LTLIBOBJS' | |
314 | 314 | ac_subst_files='' |
315 | 315 | |
316 | 316 | # Initialize some variables set by options. |
@@ -2398,6 +2398,46 @@ else | ||
2398 | 2398 | AR="$ac_cv_prog_AR" |
2399 | 2399 | fi |
2400 | 2400 | |
2401 | + # Extract the first word of "awk", so it can be a program name with args. | |
2402 | +set dummy awk; ac_word=$2 | |
2403 | +echo "$as_me:$LINENO: checking for $ac_word" >&5 | |
2404 | +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 | |
2405 | +if test "${ac_cv_path_AWK_INTERPRETER+set}" = set; then | |
2406 | + echo $ECHO_N "(cached) $ECHO_C" >&6 | |
2407 | +else | |
2408 | + case $AWK_INTERPRETER in | |
2409 | + [\\/]* | ?:[\\/]*) | |
2410 | + ac_cv_path_AWK_INTERPRETER="$AWK_INTERPRETER" # Let the user override the test with a path. | |
2411 | + ;; | |
2412 | + *) | |
2413 | + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | |
2414 | +for as_dir in $PATH | |
2415 | +do | |
2416 | + IFS=$as_save_IFS | |
2417 | + test -z "$as_dir" && as_dir=. | |
2418 | + for ac_exec_ext in '' $ac_executable_extensions; do | |
2419 | + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | |
2420 | + ac_cv_path_AWK_INTERPRETER="$as_dir/$ac_word$ac_exec_ext" | |
2421 | + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 | |
2422 | + break 2 | |
2423 | + fi | |
2424 | +done | |
2425 | +done | |
2426 | + | |
2427 | + test -z "$ac_cv_path_AWK_INTERPRETER" && ac_cv_path_AWK_INTERPRETER="/bin/awk" | |
2428 | + ;; | |
2429 | +esac | |
2430 | +fi | |
2431 | +AWK_INTERPRETER=$ac_cv_path_AWK_INTERPRETER | |
2432 | + | |
2433 | +if test -n "$AWK_INTERPRETER"; then | |
2434 | + echo "$as_me:$LINENO: result: $AWK_INTERPRETER" >&5 | |
2435 | +echo "${ECHO_T}$AWK_INTERPRETER" >&6 | |
2436 | +else | |
2437 | + echo "$as_me:$LINENO: result: no" >&5 | |
2438 | +echo "${ECHO_T}no" >&6 | |
2439 | +fi | |
2440 | + | |
2401 | 2441 | ac_aux_dir= |
2402 | 2442 | for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do |
2403 | 2443 | if test -f $ac_dir/install-sh; then |
@@ -4235,9 +4275,9 @@ done | ||
4235 | 4275 | |
4236 | 4276 | |
4237 | 4277 | # Object modules required to build the `gencat' executable. |
4238 | -# We need `mkstemp', `nl_langinfo' and `basename'; if these are | |
4239 | -# already available in system libraries, just use the provided | |
4240 | -# implementations, otherwise we must supply them. | |
4278 | +# We need `mkstemp', `nl_langinfo', `getopt_long_only' and `basename'; | |
4279 | +# if these are already available in system libraries, just use the | |
4280 | +# provided implementations, otherwise we must supply them. | |
4241 | 4281 | # |
4242 | 4282 | |
4243 | 4283 | for ac_func in mkstemp |
@@ -4448,6 +4488,112 @@ fi | ||
4448 | 4488 | done |
4449 | 4489 | |
4450 | 4490 | |
4491 | +for ac_func in getopt_long_only | |
4492 | +do | |
4493 | +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` | |
4494 | +echo "$as_me:$LINENO: checking for $ac_func" >&5 | |
4495 | +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 | |
4496 | +if eval "test \"\${$as_ac_var+set}\" = set"; then | |
4497 | + echo $ECHO_N "(cached) $ECHO_C" >&6 | |
4498 | +else | |
4499 | + cat >conftest.$ac_ext <<_ACEOF | |
4500 | +/* confdefs.h. */ | |
4501 | +_ACEOF | |
4502 | +cat confdefs.h >>conftest.$ac_ext | |
4503 | +cat >>conftest.$ac_ext <<_ACEOF | |
4504 | +/* end confdefs.h. */ | |
4505 | +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. | |
4506 | + For example, HP-UX 11i <limits.h> declares gettimeofday. */ | |
4507 | +#define $ac_func innocuous_$ac_func | |
4508 | + | |
4509 | +/* System header to define __stub macros and hopefully few prototypes, | |
4510 | + which can conflict with char $ac_func (); below. | |
4511 | + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since | |
4512 | + <limits.h> exists even on freestanding compilers. */ | |
4513 | + | |
4514 | +#ifdef __STDC__ | |
4515 | +# include <limits.h> | |
4516 | +#else | |
4517 | +# include <assert.h> | |
4518 | +#endif | |
4519 | + | |
4520 | +#undef $ac_func | |
4521 | + | |
4522 | +/* Override any gcc2 internal prototype to avoid an error. */ | |
4523 | +#ifdef __cplusplus | |
4524 | +extern "C" | |
4525 | +{ | |
4526 | +#endif | |
4527 | +/* We use char because int might match the return type of a gcc2 | |
4528 | + builtin and then its argument prototype would still apply. */ | |
4529 | +char $ac_func (); | |
4530 | +/* The GNU C library defines this for functions which it implements | |
4531 | + to always fail with ENOSYS. Some functions are actually named | |
4532 | + something starting with __ and the normal name is an alias. */ | |
4533 | +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) | |
4534 | +choke me | |
4535 | +#else | |
4536 | +char (*f) () = $ac_func; | |
4537 | +#endif | |
4538 | +#ifdef __cplusplus | |
4539 | +} | |
4540 | +#endif | |
4541 | + | |
4542 | +int | |
4543 | +main () | |
4544 | +{ | |
4545 | +return f != $ac_func; | |
4546 | + ; | |
4547 | + return 0; | |
4548 | +} | |
4549 | +_ACEOF | |
4550 | +rm -f conftest.$ac_objext conftest$ac_exeext | |
4551 | +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 | |
4552 | + (eval $ac_link) 2>conftest.er1 | |
4553 | + ac_status=$? | |
4554 | + grep -v '^ *+' conftest.er1 >conftest.err | |
4555 | + rm -f conftest.er1 | |
4556 | + cat conftest.err >&5 | |
4557 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 | |
4558 | + (exit $ac_status); } && | |
4559 | + { ac_try='test -z "$ac_c_werror_flag" | |
4560 | + || test ! -s conftest.err' | |
4561 | + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 | |
4562 | + (eval $ac_try) 2>&5 | |
4563 | + ac_status=$? | |
4564 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 | |
4565 | + (exit $ac_status); }; } && | |
4566 | + { ac_try='test -s conftest$ac_exeext' | |
4567 | + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 | |
4568 | + (eval $ac_try) 2>&5 | |
4569 | + ac_status=$? | |
4570 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 | |
4571 | + (exit $ac_status); }; }; then | |
4572 | + eval "$as_ac_var=yes" | |
4573 | +else | |
4574 | + echo "$as_me: failed program was:" >&5 | |
4575 | +sed 's/^/| /' conftest.$ac_ext >&5 | |
4576 | + | |
4577 | +eval "$as_ac_var=no" | |
4578 | +fi | |
4579 | +rm -f conftest.err conftest.$ac_objext \ | |
4580 | + conftest$ac_exeext conftest.$ac_ext | |
4581 | +fi | |
4582 | +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 | |
4583 | +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 | |
4584 | +if test `eval echo '${'$as_ac_var'}'` = yes; then | |
4585 | + cat >>confdefs.h <<_ACEOF | |
4586 | +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 | |
4587 | +_ACEOF | |
4588 | + | |
4589 | +else | |
4590 | + LOCAL_HEADERS="getopt.h ${LOCAL_HEADERS}" | |
4591 | + | |
4592 | + GENCAT_OBJECTS=${GENCAT_OBJECTS}' getopt.$(OBJEXT)' | |
4593 | +fi | |
4594 | +done | |
4595 | + | |
4596 | + | |
4451 | 4597 | for ac_func in basename |
4452 | 4598 | do |
4453 | 4599 | as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` |
@@ -5691,6 +5837,7 @@ s,@OBJEXT@,$OBJEXT,;t t | ||
5691 | 5837 | s,@LN_S@,$LN_S,;t t |
5692 | 5838 | s,@AR@,$AR,;t t |
5693 | 5839 | s,@ac_ct_AR@,$ac_ct_AR,;t t |
5840 | +s,@AWK_INTERPRETER@,$AWK_INTERPRETER,;t t | |
5694 | 5841 | s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t |
5695 | 5842 | s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t |
5696 | 5843 | s,@INSTALL_DATA@,$INSTALL_DATA,;t t |
@@ -6199,4 +6346,4 @@ if test "$no_create" != yes; then | ||
6199 | 6346 | fi |
6200 | 6347 | |
6201 | 6348 | # |
6202 | -# $RCSfile$Revision: 1.3 $: end of file | |
6349 | +# $RCSfile$Revision: 1.4 $: end of file |
@@ -3,7 +3,7 @@ | ||
3 | 3 | # |
4 | 4 | # $Id$ |
5 | 5 | # |
6 | -# Copyright (C) 2006, 2007, MinGW Project | |
6 | +# Copyright (C) 2006, 2007, 2008, MinGW Project | |
7 | 7 | # Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
8 | 8 | # |
9 | 9 | # Package identification. |
@@ -62,6 +62,7 @@ | ||
62 | 62 | AC_PROG_CC |
63 | 63 | AC_PROG_LN_S |
64 | 64 | AC_CHECK_TOOL([AR], [ar], [ar]) |
65 | + AC_PATH_PROG([AWK_INTERPRETER], [awk], [/bin/awk]) | |
65 | 66 | AC_PROG_INSTALL |
66 | 67 | |
67 | 68 | # Check if Win32 DLLs should be built, |
@@ -102,12 +103,13 @@ | ||
102 | 103 | MINGW_AC_LC_EXTENSIONS([LOCAL_HEADERS]) |
103 | 104 | |
104 | 105 | # Object modules required to build the `gencat' executable. |
105 | -# We need `mkstemp', `nl_langinfo' and `basename'; if these are | |
106 | -# already available in system libraries, just use the provided | |
107 | -# implementations, otherwise we must supply them. | |
106 | +# We need `mkstemp', `nl_langinfo', `getopt_long_only' and `basename'; | |
107 | +# if these are already available in system libraries, just use the | |
108 | +# provided implementations, otherwise we must supply them. | |
108 | 109 | # |
109 | 110 | GENCAT_AC_FUNC_MKSTEMP |
110 | 111 | GENCAT_AC_FUNC_NL_LANGINFO |
112 | + GENCAT_AC_FUNC_GETOPT_LONG_ONLY | |
111 | 113 | GENCAT_AC_FUNC_BASENAME |
112 | 114 | # |
113 | 115 | # The remainder are always provided by this package. |
@@ -127,4 +129,4 @@ | ||
127 | 129 | AC_CONFIG_FILES([Makefile]) |
128 | 130 | AC_OUTPUT |
129 | 131 | # |
130 | -# $RCSfile$Revision: 1.3 $: end of file | |
132 | +# $RCSfile$Revision: 1.4 $: end of file |
@@ -3,12 +3,12 @@ | ||
3 | 3 | * |
4 | 4 | * $Id$ |
5 | 5 | * |
6 | - * Copyright (C) 2006, 2007, Keith Marshall | |
6 | + * Copyright (C) 2006, 2007, 2008, Keith Marshall | |
7 | 7 | * |
8 | 8 | * This file implements the `main' function for the `gencat' program. |
9 | 9 | * |
10 | 10 | * Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
11 | - * Last modification: 12-May-2007 | |
11 | + * Last modification: 08-Jan-2008 | |
12 | 12 | * |
13 | 13 | * |
14 | 14 | * This is free software. It is provided AS IS, in the hope that it may |
@@ -26,6 +26,14 @@ | ||
26 | 26 | * MA 02110-1301, USA. |
27 | 27 | * |
28 | 28 | */ |
29 | +#define PROGRAM_IDENTITY progname, PACKAGE_VERSION | |
30 | + | |
31 | +#define AUTHOR_IDENTITY "Keith Marshall" | |
32 | +#define AUTHOR_ATTRIBUTION AUTHOR_IDENTITY" for the MinGW Project" | |
33 | + | |
34 | +#define COPYRIGHT_YEARS "2006, 2007, 2008" | |
35 | +#define COPYRIGHT_HOLDER COPYRIGHT_YEARS, AUTHOR_IDENTITY | |
36 | +#define COPYRIGHT_NOTICE MSG_COPYRIGHT_NOTICE, COPYRIGHT_HOLDER | |
29 | 37 | |
30 | 38 | #ifdef HAVE_CONFIG_H |
31 | 39 | #include <config.h> |
@@ -34,10 +42,12 @@ | ||
34 | 42 | #include <fcntl.h> |
35 | 43 | #include <stdio.h> |
36 | 44 | #include <stdlib.h> |
45 | +#include <stdarg.h> | |
37 | 46 | #include <string.h> |
38 | 47 | #include <sys/types.h> |
39 | 48 | #include <sys/stat.h> |
40 | 49 | #include <unistd.h> |
50 | +#include <getopt.h> | |
41 | 51 | #include <libgen.h> |
42 | 52 | #include <errno.h> |
43 | 53 |
@@ -54,12 +64,60 @@ char *progname, *invoked; | ||
54 | 64 | int gencat_errno = 0; |
55 | 65 | nl_catd gencat_messages; |
56 | 66 | |
67 | +/* Option control flags, for printing of program identification banners, | |
68 | + * as required for `help', `version' and copyright notifications. | |
69 | + */ | |
70 | +#define print_top_banner 0x08 | |
71 | +#define print_nl_duplicate 0x04 | |
72 | + | |
73 | +/* Standard arguments, to include in a program identification banner. | |
74 | + */ | |
75 | +#define top_banner_text PROGRAM_IDENTITY, AUTHOR_ATTRIBUTION | |
76 | + | |
77 | +static | |
78 | +void banner_printf( int opts, int set, int msg, const char *fmt, ... ) | |
79 | +{ | |
80 | + /* A helper function, for printing banner notifications. | |
81 | + */ | |
82 | + va_list args; | |
83 | + const char *nl_fmt = catgets( gencat_messages, set, msg, NULL ); | |
84 | + | |
85 | + if( opts & print_top_banner ) | |
86 | + printf( catgets( gencat_messages, MSG_PROGRAM_BANNER ), top_banner_text ); | |
87 | + | |
88 | + va_start( args, fmt ); | |
89 | + if( (nl_fmt == NULL) || ((opts & print_nl_duplicate) != 0) ) | |
90 | + /* | |
91 | + * A national language translation has been provided, but the | |
92 | + * English version must also be displayed, or there is no available | |
93 | + * translation, so we just print the English text anyway. | |
94 | + */ | |
95 | + vprintf( fmt, args ); | |
96 | + | |
97 | + if( nl_fmt != NULL ) | |
98 | + /* | |
99 | + * When we found a national language translation, we print it. | |
100 | + */ | |
101 | + vprintf( nl_fmt, args ); | |
102 | + va_end( args ); | |
103 | +} | |
104 | + | |
57 | 105 | int main( int argc, char **argv ) |
58 | 106 | { |
107 | + struct option options[] = | |
108 | + { | |
109 | + /* The options understood by this version of `gencat'; | |
110 | + * all are long form, to be evaluated by getopt_long_only(). | |
111 | + */ | |
112 | + { "help", no_argument, NULL, 'h' }, | |
113 | + { "version", no_argument, NULL, 'v' }, | |
114 | + { NULL, 0, NULL, 0 } | |
115 | + }; | |
116 | + | |
59 | 117 | char *msgcat; |
60 | 118 | char *outfile = NULL; |
61 | 119 | |
62 | - int mc, numsets, setnum, msgcount; | |
120 | + int opt, mc, numsets, setnum, msgcount; | |
63 | 121 | off_t offset, msg_index_offset; |
64 | 122 | |
65 | 123 | char tmpcat[] = "mcXXXXXX"; |
@@ -83,14 +141,51 @@ int main( int argc, char **argv ) | ||
83 | 141 | progname = basename( invoked = *argv ); |
84 | 142 | gencat_messages = catopen( "gencat", NL_CAT_LOCALE ); |
85 | 143 | |
144 | + if( (*argv = strdup( progname )) != NULL ) | |
145 | + { | |
146 | + /* Set up the form of the program name to display in diagnostics; | |
147 | + * exclude the path component, and discard any `.exe' suffix. | |
148 | + */ | |
149 | + int ext = strlen( *argv ) - 4; | |
150 | + if( (ext > 0) && (strcasecmp( *argv + ext, ".exe" ) == 0) ) | |
151 | + *(*argv + ext) = '\0'; | |
152 | + progname = *argv; | |
153 | + } | |
154 | + else | |
155 | + /* Something went wrong... | |
156 | + * retain the basename from the original program path name, | |
157 | + * as the effective program name. | |
158 | + */ | |
159 | + *argv = progname; | |
160 | + | |
161 | + /* Evaluate any options, specified on the command line. | |
162 | + */ | |
163 | + while( (opt = getopt_long_only( argc, argv, "vh", options, NULL )) != -1 ) | |
164 | + switch( opt ) | |
165 | + { | |
166 | + case 'h': | |
167 | + /* | |
168 | + * This is a request to display a help message. | |
169 | + */ | |
170 | + banner_printf( print_top_banner, MSG_GENCAT_SYNOPSIS, *argv ); | |
171 | + exit( EXIT_SUCCESS ); | |
172 | + | |
173 | + case 'v': | |
174 | + /* | |
175 | + * And this is for display of version and copyright info. | |
176 | + */ | |
177 | + banner_printf( print_top_banner + print_nl_duplicate, COPYRIGHT_NOTICE ); | |
178 | + exit( EXIT_SUCCESS ); | |
179 | + } | |
180 | + | |
86 | 181 | cat_index.id = tag; |
87 | 182 | |
88 | - if( --argc > 1 ) | |
183 | + if( (argc -= optind) > 1 ) | |
89 | 184 | { |
90 | 185 | /* Initialise the message list, to incorporate any messages which |
91 | 186 | * are already contained within the specified message catalogue. |
92 | 187 | */ |
93 | - if( (cat = mc_load( msgcat = *++argv )) == NULL ) | |
188 | + if( (cat = mc_load( msgcat = *(argv += optind) )) == NULL ) | |
94 | 189 | switch( errno ) |
95 | 190 | { |
96 | 191 | case ENOENT: |
@@ -110,23 +205,39 @@ int main( int argc, char **argv ) | ||
110 | 205 | while( --argc ) |
111 | 206 | cat = mc_merge( cat, mc_source( *++argv )); |
112 | 207 | |
208 | + /* Walk the resultant in-memory linked message list, counting... | |
209 | + */ | |
113 | 210 | msgcount = numsets = setnum = 0; |
114 | 211 | for( curr = cat; curr != NULL; curr = curr->link ) |
115 | 212 | { |
213 | + /* the number of individual messages defined... | |
214 | + */ | |
116 | 215 | ++msgcount; |
117 | 216 | if( curr->set > setnum ) |
118 | 217 | { |
218 | + /* and the number of distinct message sets, | |
219 | + * to which they are allocated. | |
220 | + */ | |
119 | 221 | ++numsets; |
120 | 222 | setnum = curr->set; |
121 | 223 | } |
122 | 224 | } |
123 | 225 | dfprintf(( stderr, "%u messages in %u sets\n", msgcount, numsets )); |
226 | + | |
227 | + /* Compute the required image size for the message catalogue index, | |
228 | + * and allocate memory in which to construct it... | |
229 | + */ | |
124 | 230 | offset = ( numsets + msgcount ) * sizeof( struct key ); |
125 | 231 | if( (set_index = mc_malloc( offset )) == NULL ) |
126 | 232 | { |
233 | + /* bailing out, if insufficient memory. | |
234 | + */ | |
127 | 235 | fprintf( errmsg( MSG_OUT_OF_MEMORY ), progname ); |
128 | 236 | return( EXIT_FAILURE ); |
129 | 237 | } |
238 | + /* Locate the start of the message index entries, | |
239 | + * within the composite set and message index image. | |
240 | + */ | |
130 | 241 | msg_index = set_index + numsets; |
131 | 242 | |
132 | 243 | /* Create a temporary output file, |
@@ -141,67 +252,134 @@ int main( int argc, char **argv ) | ||
141 | 252 | return EXIT_FAILURE; |
142 | 253 | } |
143 | 254 | |
255 | + /* Write out the standard message catalogue header record, | |
256 | + * then seek beyond the space required for the index image, | |
257 | + * to commence writing out the message data. | |
258 | + */ | |
144 | 259 | write( mc, &cat_index, sizeof( MSGCAT ) ); |
145 | 260 | offset = lseek( mc, offset, SEEK_CUR ); |
146 | - setnum = 0; | |
261 | + | |
262 | + /* Compute the offset, ON DISK, for the start of the message | |
263 | + * index, within the composite set and message index image, in | |
264 | + * terms of its physical byte count from start of file. | |
265 | + */ | |
147 | 266 | msg_index_offset = sizeof( MSGCAT ) + numsets * sizeof( struct key ); |
267 | + | |
268 | + /* Forcing a set number transition into the first message set... | |
269 | + */ | |
270 | + setnum = 0; | |
271 | + /* | |
272 | + * Walk the in-memory linked message list again... | |
273 | + */ | |
148 | 274 | for( curr = cat; curr != NULL; curr = curr->link ) |
149 | 275 | { |
276 | + /* adding a new set index entry, on each set number transition... | |
277 | + */ | |
150 | 278 | if( curr->set > setnum ) |
151 | 279 | { |
280 | + /* incorporating the applicable set number, | |
281 | + * and the ON-DISK byte offset for the index entry | |
282 | + * associated with its first included message. | |
283 | + */ | |
152 | 284 | set_index->setnum = setnum = curr->set; |
153 | 285 | (set_index++)->offset = msg_index_offset; |
154 | 286 | } |
287 | + /* Adjust the cumulative computed value of the ON-DISK | |
288 | + * message index offset, to account for each message traversed... | |
289 | + */ | |
155 | 290 | msg_index_offset += sizeof( struct key ); |
291 | + /* | |
292 | + * while incorporating the appropriate message number, | |
293 | + * and message data offset, into the in-memory image of | |
294 | + * the message index. | |
295 | + */ | |
156 | 296 | msg_index->msgnum = curr->msg; |
157 | 297 | (msg_index++)->offset = offset; |
158 | - | |
298 | + /* | |
299 | + * and write out the message data, to the catalogue file, | |
300 | + * updating `offset' to track where the data for the NEXT message, | |
301 | + * if any, is to be written. | |
302 | + */ | |
159 | 303 | offset += write( mc, curr->base + curr->loc, curr->len ); |
160 | 304 | } |
161 | 305 | |
162 | - set_index = msg_index - numsets - msgcount; | |
306 | + /* Rewind the catalogue, to the start of the reserved index space... | |
307 | + */ | |
163 | 308 | lseek( mc, sizeof( MSGCAT ), SEEK_SET ); |
309 | + /* | |
310 | + * Locate the start of the in-memory image of the index, once more, | |
311 | + * and copy it into the generated message catalogue. | |
312 | + */ | |
313 | + set_index = msg_index - numsets - msgcount; | |
164 | 314 | write( mc, set_index, (numsets + msgcount) * sizeof( struct key ) ); |
165 | 315 | |
316 | + /* Check message catalogue generation status... | |
317 | + */ | |
166 | 318 | if( gencat_errno == 0 ) |
167 | 319 | { |
320 | + /* Completed without error... | |
321 | + */ | |
168 | 322 | if( outfile == NULL ) |
323 | + /* | |
324 | + * Always true, at present... | |
325 | + * (this is here to accommodate a possible future implementation | |
326 | + * of an `--output-file=NAME' option, to facilitate including an | |
327 | + * existing message catalogue into a new, and differently named, | |
328 | + * derivative message catalogue). | |
329 | + */ | |
169 | 330 | outfile = msgcat; |
170 | 331 | |
171 | 332 | if( strcmp( outfile, "-" ) == 0 ) |
172 | 333 | { |
334 | + /* This is emitting the message catalogue content to the standard | |
335 | + * output stream; rewind the temporary catalogue file, read back, | |
336 | + * and then rewrite its content to the stdout stream. | |
337 | + */ | |
173 | 338 | int count; |
174 | 339 | char buf[ BUFSIZ ]; |
175 | 340 | lseek( mc, (off_t)(0), SEEK_SET ); |
176 | 341 | while( (count = read( mc, buf, BUFSIZ )) > 0 ) |
177 | 342 | write( STDOUT_FILENO, buf, count ); |
343 | + | |
344 | + /* When done, close and delete the temporary file. | |
345 | + */ | |
178 | 346 | close( mc ); |
179 | 347 | remove( tmpcat ); |
180 | 348 | } |
181 | 349 | else |
182 | 350 | { |
351 | + /* This is saving the message catalogue as a permanent disk file, | |
352 | + * overwriting any previously existing version; this is achieved by | |
353 | + * simply renaming the temporary file, and setting its attributes | |
354 | + * appropriately. | |
355 | + */ | |
183 | 356 | close( mc ); |
184 | 357 | rename( tmpcat, outfile ); |
185 | 358 | chmod( outfile, 0644 ); |
186 | 359 | } |
187 | 360 | } |
188 | 361 | else |
189 | - { | |
362 | + { /* An error occurred... | |
363 | + * The temporary file is likely to be corrupt, | |
364 | + * so simply discard it, and report failure. | |
365 | + */ | |
190 | 366 | close( mc ); |
191 | 367 | remove( tmpcat ); |
368 | + return EXIT_FAILURE; | |
192 | 369 | } |
193 | 370 | } |
194 | 371 | |
195 | 372 | else |
196 | - { | |
197 | - /* User specified insufficient command line arguments. | |
373 | + { /* User specified insufficient command line arguments. | |
198 | 374 | * Diagnose, and bail out. |
199 | 375 | */ |
200 | 376 | fprintf( errmsg( MSG_MISSING_ARGS ), progname ); |
201 | 377 | fprintf( errmsg( MSG_GENCAT_USAGE ), progname ); |
202 | 378 | return EXIT_FAILURE; |
203 | 379 | } |
380 | + /* On successful completion, report it. | |
381 | + */ | |
204 | 382 | return EXIT_SUCCESS; |
205 | 383 | } |
206 | 384 | |
207 | -/* $RCSfile$Revision: 1.1.1.1 $: end of file */ | |
385 | +/* $RCSfile$Revision: 1.2 $: end of file */ |
@@ -29,11 +29,19 @@ | ||
29 | 29 | # message set. |
30 | 30 | # |
31 | 31 | # <message text> is the fallback text defined for the message; it |
32 | -# must all on the same line as the `#define' token. | |
32 | +# must all appear on the same line as the `#define' | |
33 | +# token, or that line must terminate with a reverse | |
34 | +# solidus, so escaping the newline, to indicate that | |
35 | +# the following line is to be subsumed as a logical | |
36 | +# continuation of the `#define' line; continuation, | |
37 | +# in this manner, may be extended over any number | |
38 | +# of consecutive input lines, by similarly escaping | |
39 | +# the terminal newline on all but the last physical | |
40 | +# input line of any such single logical line. | |
33 | 41 | # |
34 | 42 | # |
35 | 43 | # Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
36 | -# Last modification: 05-Mar-2007 | |
44 | +# Last modification: 02-Jan-2008 | |
37 | 45 | # |
38 | 46 | # |
39 | 47 | # This is free software. It is provided AS IS, in the hope that it may |
@@ -53,7 +61,29 @@ | ||
53 | 61 | |
54 | 62 | # Establish the default convention for identifying message definitions. |
55 | 63 | # |
56 | - BEGIN { MSGTAG = "MSG_[A-Z_a-z0-9]+" } | |
64 | + BEGIN { MSGTAG = "MSG_[A-Z_a-z0-9]+"; MULTILINE = 0 } | |
65 | +# | |
66 | +# If we enabled MULTILINE mode, on the preceding input line, then we treat | |
67 | +# the current input line as a logical continuation of the preceding line. | |
68 | +# We must handle this case *before* any other condition, because such line | |
69 | +# continuation overrides any other line type identification checks. | |
70 | +# | |
71 | + MULTILINE == 1 { | |
72 | +# | |
73 | +# If this continuation line is not itself continued, | |
74 | +# then we turn off MULTILINE, effective from the *next* input line. | |
75 | +# | |
76 | + if( $0 !~ /\\$/ ) MULTILINE = 0; | |
77 | +# | |
78 | +# We then emit the continuation line, and immediately proceed to | |
79 | +# the next input line. | |
80 | +# | |
81 | ||
82 | + next | |
83 | + } | |
84 | +# | |
85 | +# If we are *not* in MULTILINE mode, then we proceed to the normal input | |
86 | +# line interpretation strategy... | |
57 | 87 | # |
58 | 88 | # Allow the user to substitute an alternative identification convention, |
59 | 89 | # by assigning a new MSGTAG value in the input stream. |
@@ -77,6 +107,12 @@ | ||
77 | 107 | { sub( "^#[ ]*define[ ]+", "# define " ) } |
78 | 108 | $1$2 == "#define" && match( $3, MSGTAG ) == 1 && RLENGTH == length( $3 ){ |
79 | 109 | # |
110 | +# Only lines, such as this, which begin with a `#define' token, are permitted | |
111 | +# to initiate MULTILINE continuation mode; when such a line is terminated by | |
112 | +# a reverse solidus escaped newline, then initiate MULTILINE mode. | |
113 | +# | |
114 | + if( $0 ~ /\\$/ ) MULTILINE = 1 | |
115 | +# | |
80 | 116 | # Extract the set number from the message definition; |
81 | 117 | # if it differs from that of the set identified by CURSET, |
82 | 118 | # then start a new set. |
@@ -106,4 +142,4 @@ | ||
106 | 142 | print MSGNUM, $0 |
107 | 143 | } |
108 | 144 | # |
109 | -# $RCSfile$Revision: end of file | |
145 | +# $RCSfile$Revision$: end of file |
@@ -7,7 +7,7 @@ | ||
7 | 7 | * !$ Message definitions for MinGW implementation of `gencat'. |
8 | 8 | * !$ |
9 | 9 | * !$ $Id$ |
10 | - * !$ Copyright (C) 2006, 2007, MinGW Project | |
10 | + * !$ Copyright (C) 2006, 2007, 2008, MinGW Project | |
11 | 11 | * !$ Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
12 | 12 | * !$ |
13 | 13 | * !$ This file has been automatically generated from `gcmsgs.h', |
@@ -35,29 +35,113 @@ | ||
35 | 35 | * !$ |
36 | 36 | * !$quote " |
37 | 37 | * ! |
38 | + * !$ When translating these message definitions, please take care | |
39 | + * !$ to preserve the number and order of `printf' format tags; (i.e. | |
40 | + * !$ tags of the form `%c', where `c' is any alphabetic character). | |
41 | + * !$ Also please note the usage of `\n' to insert a line break into | |
42 | + * !$ any message definition, and the use of a `\` following the | |
43 | + * !$ closing quote, on all but the last line of a multiline message | |
44 | + * !$ definition; there must be no white space between the quote and | |
45 | + * !$ the following `\', nor following the `\' itself. | |
46 | + * ! | |
47 | + * ! | |
48 | + * !$ Message set #1 is reserved for the program banner, which is | |
49 | + * !$ displayed when either the `-help' or the `-version' option is | |
50 | + * !$ invoked; it is discretional whether a translation of this, in | |
51 | + * !$ the national language, is provided. If not, then set #1 may be | |
52 | + * !$ excluded from the message catalogue, or the banner template | |
53 | + * !$ may be left untranslated, in which case the banner will be | |
54 | + * !$ displayed in its original English language form. | |
55 | + * ! | |
56 | + */ | |
57 | +#define MSG_PROGRAM_BANNER 1, 1, \ | |
58 | +"%s (MinGW catgets SubSystem for MS-Windows), Version %s\n"\ | |
59 | +"Written by %s\n" | |
60 | +/* | |
61 | + * ! | |
62 | + * !$ Messages in set #2 are reserved for use by the `-version' option, | |
63 | + * !$ and are displayed *both* in English *and* in the national language. | |
64 | + * !$ While it is not normally necessary to provide an English language | |
65 | + * !$ message catalogue, if one is provided, it should *exclude* all of | |
66 | + * !$ the messages defined in set #2, to avoid displaying identical | |
67 | + * !$ copies of these messages twice. | |
68 | + * ! | |
69 | + */ | |
70 | +#define MSG_COPYRIGHT_NOTICE 2, 3, "\nCopyright (C) %s, %s.\n"\ | |
71 | +"This is free software; see the source for copying conditions. There is NO\n"\ | |
72 | +"WARRANTY OF ANY KIND, not even an IMPLIED WARRANTY OF MERCHANTABILITY, nor\n"\ | |
73 | +"of FITNESS FOR ANY PARTICULAR PURPOSE.\n" | |
74 | +/* | |
75 | + * ! | |
76 | + * !$ Set #3 is reserved for the synopsis displayed by the `-help' option; | |
77 | + * !$ in general, a national language version of this should be provided. | |
78 | + * ! | |
79 | + */ | |
80 | +#define MSG_GENCAT_SYNOPSIS 3, 2, \ | |
81 | +"\nUsage: %s catalogue-name input-file ...\n"\ | |
82 | +"\nDescription\n"\ | |
83 | +" Generate, or update, the national language message catalogue specified\n"\ | |
84 | +" by `catalogue-name', (which is a binary file, in the format required by\n"\ | |
85 | +" the MinGW implementation of the POSIX `catgets' facility), reading the\n"\ | |
86 | +" message definitions from each specified `input-file' in turn.\n"\ | |
87 | +"\nOptions\n"\ | |
88 | +" In normal use, there are no options. However, for compatibility with\n"\ | |
89 | +" GNU standard utilities, the following are accepted:--\n\n"\ | |
90 | +" -help, --help\n"\ | |
91 | +" Display this program synopsis, and exit.\n\n"\ | |
92 | +" -version, --version\n"\ | |
93 | +" Display program identification, and copyright notice,\n"\ | |
94 | +" then exit.\n\n" | |
95 | +/* | |
96 | + * ! | |
97 | + * !$ Set #4 specifies messages relating to `gencat' program invocation, | |
98 | + * !$ or to runtime problems; they should always be translated to the | |
99 | + * !$ applicable national language. | |
100 | + * ! | |
101 | + */ | |
102 | +#define MSG_MISSING_ARGS 4, 1, "%s: incorrect number of arguments\n" | |
103 | +#define MSG_GENCAT_USAGE 4, 2, "usage: %s catalogue-name input-file ...\n" | |
104 | +#define MSG_OUTPUT_NOFILE 4, 3, "%s: %s: cannot create temporary output file\n" | |
105 | +#define MSG_OUT_OF_MEMORY 4, 4, "%s: out of memory\n" | |
106 | +#define MSG_INTERNAL_ERROR 4, 5, "%s: internal error: %s\n" | |
107 | +/* | |
108 | + * ! | |
109 | + * !$ Set #5 defines messages relating to problems in interpretation of | |
110 | + * !$ the content, or format, of the input files, or any pre-existing | |
111 | + * !$ version of the message catalogue which is being updated; national | |
112 | + * !$ language translations should be provided. | |
113 | + * ! | |
114 | + */ | |
115 | +#define MSG_BAD_CATALOGUE 5, 1, "%s: %s: file is not a valid message catalogue\n" | |
116 | +#define MSG_UNKNOWN_CODESET 5, 2, "%s: %s: unknown codeset descriptor\n" | |
117 | +#define MSG_CODESET_CLASH 5, 3, "%s:%u: codeset `%s' conflicts with prior declaration\n" | |
118 | +#define MSG_HAD_CODESET 5, 4, "%s:%u: codeset `%s' previously declared here\n" | |
119 | +#define MSG_SETNUM_NOT_INCR 5, 5, "invalid set number: expecting > %d; got %d\n" | |
120 | +#define MSG_MSGNUM_NOT_INCR 5, 6, "invalid message number: expecting > %d; got %d\n" | |
121 | +#define MSG_REDEFINED 5, 7, "%s: %s:%u: redefinition of message %u in set %u\n" | |
122 | +#define MSG_PREVIOUS_HERE 5, 8, "%s: %s:%u: previous definition was here\n" | |
123 | +/* | |
124 | + * ! | |
125 | + * !$ Set #6 defines messages relating to abnormal conditions occuring | |
126 | + * !$ when the end of an input file is encountered; again, national | |
127 | + * !$ language translations should be provided. | |
128 | + * ! | |
129 | + */ | |
130 | +#define MSG_EOF_IN_QUOTES 6, 2, "%s:%u: unexpected EOF encountered before closing quote\n" | |
131 | +#define MSG_TEXT_DISCARDED 6, 3, "%s:%u: incomplete message marked for deletion\n" | |
132 | +#define MSG_MISSING_NEWLINE 6, 4, "%s:%u: missing newline at end of file\n" | |
133 | +#define MSG_BAD_INDEX 6, 5, "invalid reference in message index" | |
134 | +/* | |
135 | + * ! | |
136 | + * !$ Set #7 defines messages relating to malformed Unicode input streams; | |
137 | + * !$ once again, national language translations should be provided. | |
138 | + * ! | |
38 | 139 | */ |
39 | -#define MSG_MISSING_ARGS 1, 1, "%s: incorrect number of arguments\n" | |
40 | -#define MSG_GENCAT_USAGE 1, 2, "usage: %s catalogue-name input-file ...\n" | |
41 | -#define MSG_OUTPUT_NOFILE 1, 3, "%s: %s: cannot create temporary output file\n" | |
42 | -#define MSG_OUT_OF_MEMORY 1, 4, "%s: out of memory\n" | |
43 | -#define MSG_INTERNAL_ERROR 1, 5, "%s: internal error: %s\n" | |
44 | -#define MSG_BAD_CATALOGUE 2, 1, "%s: %s: file is not a valid message catalogue\n" | |
45 | -#define MSG_UNKNOWN_CODESET 2, 2, "%s: %s: unknown codeset descriptor\n" | |
46 | -#define MSG_CODESET_CLASH 2, 3, "%s:%u: codeset `%s' conflicts with prior declaration\n" | |
47 | -#define MSG_HAD_CODESET 2, 4, "%s:%u: codeset `%s' previously declared here\n" | |
48 | -#define MSG_SETNUM_NOT_INCR 2, 5, "invalid set number: expecting > %d; got %d\n" | |
49 | -#define MSG_MSGNUM_NOT_INCR 2, 6, "invalid message number: expecting > %d; got %d\n" | |
50 | -#define MSG_REDEFINED 2, 7, "%s: %s:%u: redefinition of message %u in set %u\n" | |
51 | -#define MSG_PREVIOUS_HERE 2, 8, "%s: %s:%u: previous definition was here\n" | |
52 | -#define MSG_EOF_IN_QUOTES 3, 2, "%s:%u: unexpected EOF encountered before closing quote\n" | |
53 | -#define MSG_TEXT_DISCARDED 3, 3, "%s:%u: incomplete message marked for deletion\n" | |
54 | -#define MSG_MISSING_NEWLINE 3, 4, "%s:%u: missing newline at end of file\n" | |
55 | -#define MSG_BAD_INDEX 3, 5, "invalid reference in message index" | |
56 | -#define MSG_UTF_UNKNOWN 4, 1, "%s:unrecognisable encoding format\n" | |
57 | -#define MSG_UTF_SIZE_ERROR 4, 2, "%s:invalid byte count per code point; value was %d\n" | |
58 | -#define MSG_UTF_FRAME_ERROR 4, 3, "%s:%u:UTF-%u%cE input framing error\n" | |
59 | -#define MSG_UTF_CODESET 4, 4, "%s:input codeset identified as %s; conflicts with ...\n" | |
140 | +#define MSG_UTF_UNKNOWN 7, 1, "%s:unrecognisable encoding format\n" | |
141 | +#define MSG_UTF_SIZE_ERROR 7, 2, "%s:invalid byte count per code point; value was %d\n" | |
142 | +#define MSG_UTF_FRAME_ERROR 7, 3, "%s:%u:UTF-%u%cE input framing error\n" | |
143 | +#define MSG_UTF_CODESET 7, 4, "%s:input codeset identified as %s; conflicts with ...\n" | |
60 | 144 | /* ! |
61 | 145 | * !$ end of file |
62 | 146 | */ |
63 | -#endif /* !defined( GCMSGS_H ): $RCSfile$Revision: 1.3 $: end of file */ | |
147 | +#endif /* !defined( GCMSGS_H ): $RCSfile$Revision: 1.4 $: end of file */ |
@@ -0,0 +1,636 @@ | ||
1 | +/* | |
2 | + * getopt.c | |
3 | + * | |
4 | + * $Id$ | |
5 | + * | |
6 | + * Implementation of the `getopt', `getopt_long' and `getopt_long_only' | |
7 | + * APIs, for inclusion in the MinGW runtime library. | |
8 | + * | |
9 | + * This file is part of the MinGW32 package set. | |
10 | + * | |
11 | + * Contributed by Keith Marshall <keithmarshall@users.sourceforge.net> | |
12 | + * Last modification: 27-Dec-2007 | |
13 | + * | |
14 | + * THIS SOFTWARE IS NOT COPYRIGHTED | |
15 | + * | |
16 | + * This source code is offered for use in the public domain. You may | |
17 | + * use, modify or distribute it freely. | |
18 | + * | |
19 | + * This code is distributed in the hope that it will be useful but | |
20 | + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY | |
21 | + * DISCLAIMED. This includes but is not limited to warranties of | |
22 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
23 | + * | |
24 | + * $Revision$ | |
25 | + * $Author$ | |
26 | + * $Date$ | |
27 | + * | |
28 | + */ | |
29 | + | |
30 | +#include <stdio.h> | |
31 | +#include <stdlib.h> | |
32 | +#include <stdarg.h> | |
33 | +#include <getopt.h> | |
34 | + | |
35 | +/* Identify how to get the calling program name, for use in messages... | |
36 | + */ | |
37 | +#ifdef __CYGWIN__ | |
38 | +/* | |
39 | + * CYGWIN uses this DLL reference... | |
40 | + */ | |
41 | +# define PROGNAME __progname | |
42 | +extern char __declspec(dllimport) *__progname; | |
43 | +#else | |
44 | +/* | |
45 | + * ...while elsewhere, we simply use the first argument passed. | |
46 | + */ | |
47 | +# define PROGNAME *argv | |
48 | +#endif | |
49 | + | |
50 | +/* Initialise the public variables. */ | |
51 | + | |
52 | +int optind = 0; /* index for first non-option arg */ | |
53 | +int opterr = 1; /* enable built-in error messages */ | |
54 | + | |
55 | +char *optarg = NULL; /* pointer to current option argument */ | |
56 | + | |
57 | +#define CHAR char /* argument type selector */ | |
58 | + | |
59 | +#define getopt_switchar '-' /* option prefix character in argv */ | |
60 | +#define getopt_pluschar '+' /* prefix for POSIX mode in optstring */ | |
61 | +#define getopt_takes_argument ':' /* marker for optarg in optstring */ | |
62 | +#define getopt_arg_assign '=' /* longopt argument field separator */ | |
63 | +#define getopt_unknown '?' /* return code for unmatched option */ | |
64 | +#define getopt_ordered 1 /* return code for ordered non-option */ | |
65 | + | |
66 | +#define getopt_all_done -1 /* return code to indicate completion */ | |
67 | + | |
68 | +enum | |
69 | +{ /* All `getopt' API functions are implemented via calls to the | |
70 | + * common static function `getopt_parse()'; these `mode' selectors | |
71 | + * determine the behaviour of `getopt_parse()', to deliver the | |
72 | + * appropriate result in each case. | |
73 | + */ | |
74 | + getopt_mode_standard = 0, /* getopt() */ | |
75 | + getopt_mode_long, /* getopt_long() */ | |
76 | + getopt_mode_long_only /* getopt_long_only() */ | |
77 | +}; | |
78 | + | |
79 | +enum | |
80 | +{ /* When attempting to match a command line argument to a long form option, | |
81 | + * these indicate the status of the match. | |
82 | + */ | |
83 | + getopt_no_match = 0, /* no successful match */ | |
84 | + getopt_abbreviated_match, /* argument is an abbreviation for an option */ | |
85 | + getopt_exact_match /* argument matches the full option name */ | |
86 | +}; | |
87 | + | |
88 | +int optopt = getopt_unknown; /* return value for option being evaluated */ | |
89 | + | |
90 | +static __inline__ | |
91 | +int getopt_missing_arg( const CHAR *optstring ) | |
92 | +{ | |
93 | + /* Helper function to determine the appropriate return value, | |
94 | + * for the case where a required option argument is missing. | |
95 | + */ | |
96 | + if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) ) | |
97 | + ++optstring; | |
98 | + return (*optstring == getopt_takes_argument) | |
99 | + ? getopt_takes_argument | |
100 | + : getopt_unknown; | |
101 | +} | |
102 | + | |
103 | +/* `complain' macro facilitates the generation of simple built-in | |
104 | + * error messages, displayed on various fault conditions, provided | |
105 | + * `opterr' is non-zero. | |
106 | + */ | |
107 | +#define complain( MSG, ARG ) if( opterr ) \ | |
108 | + fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG ) | |
109 | + | |
110 | +static __inline__ | |
111 | +int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval ) | |
112 | +{ | |
113 | + /* Helper function, to generate more complex built-in error | |
114 | + * messages, for invalid arguments to long form options ... | |
115 | + */ | |
116 | + if( opterr ) | |
117 | + { | |
118 | + /* ... but, displayed only if `opterr' is non-zero. | |
119 | + */ | |
120 | + char flag[] = "--"; | |
121 | + if( mode != getopt_mode_long ) | |
122 | + /* | |
123 | + * only display one hyphen, for implicit long form options, | |
124 | + * improperly resolved by `getopt_long_only()'. | |
125 | + */ | |
126 | + flag[1] = 0; | |
127 | + /* | |
128 | + * always preface the program name ... | |
129 | + */ | |
130 | + fprintf( stderr, "%s: ", prog ); | |
131 | + /* | |
132 | + * to the appropriate, option specific message. | |
133 | + */ | |
134 | + fprintf( stderr, fmt, flag, opt->name ); | |
135 | + } | |
136 | + /* Whether displaying the message, or not, always set `optopt' | |
137 | + * to identify the faulty option ... | |
138 | + */ | |
139 | + optopt = opt->val; | |
140 | + /* | |
141 | + * and return the `invalid option' indicator. | |
142 | + */ | |
143 | + return retval; | |
144 | +} | |
145 | + | |
146 | +/* `getopt_conventions' establish behavioural options, to control | |
147 | + * the operation of `getopt_parse()', e.g. to select between POSIX | |
148 | + * and GNU style argument parsing behaviour. | |
149 | + */ | |
150 | +#define getopt_set_conventions 0x1000 | |
151 | +#define getopt_posixly_correct 0x0010 | |
152 | + | |
153 | +static __inline__ | |
154 | +int getopt_conventions( int flags ) | |
155 | +{ | |
156 | + static int conventions = 0; | |
157 | + | |
158 | + if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) ) | |
159 | + { | |
160 | + /* default conventions have not yet been established; | |
161 | + * initialise them now! | |
162 | + */ | |
163 | + conventions = getopt_set_conventions; | |
164 | + if( (flags == getopt_pluschar) || (getenv( "POSIXLY_CORRECT" ) != NULL) ) | |
165 | + conventions |= getopt_posixly_correct; | |
166 | + } | |
167 | + | |
168 | + else if( flags & getopt_set_conventions ) | |
169 | + /* | |
170 | + * default conventions may have already been established, | |
171 | + * but this is a specific request to augment them. | |
172 | + */ | |
173 | + conventions |= flags; | |
174 | + | |
175 | + /* in any event, return the currently established conventions. | |
176 | + */ | |
177 | + return conventions; | |
178 | +} | |
179 | + | |
180 | +static __inline__ | |
181 | +int is_switchar( CHAR flag ) | |
182 | +{ | |
183 | + /* A simple helper function, used to identify the switch character | |
184 | + * introducing an optional command line argument. | |
185 | + */ | |
186 | + return flag == getopt_switchar; | |
187 | +} | |
188 | + | |
189 | +static __inline__ | |
190 | +const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string ) | |
191 | +{ | |
192 | + /* Helper function, used to identify short form options. | |
193 | + */ | |
194 | + if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) ) | |
195 | + ++opt_string; | |
196 | + if( *opt_string == getopt_takes_argument ) | |
197 | + ++opt_string; | |
198 | + do if( lookup == *opt_string ) return opt_string; | |
199 | + while( *++opt_string ); | |
200 | + return NULL; | |
201 | +} | |
202 | + | |
203 | +static __inline__ | |
204 | +int getopt_match_long( const CHAR *nextchar, const CHAR *optname ) | |
205 | +{ | |
206 | + /* Helper function, used to identify potential matches for | |
207 | + * long form options. | |
208 | + */ | |
209 | + CHAR matchchar; | |
210 | + while( (matchchar = *nextchar++) && (matchchar == *optname) ) | |
211 | + /* | |
212 | + * skip over initial substring which DOES match. | |
213 | + */ | |
214 | + ++optname; | |
215 | + | |
216 | + if( matchchar ) | |
217 | + { | |
218 | + /* did NOT match the entire argument to an initial substring | |
219 | + * of a defined option name ... | |
220 | + */ | |
221 | + if( matchchar != getopt_arg_assign ) | |
222 | + /* | |
223 | + * ... and didn't stop at an `=' internal field separator, | |
224 | + * so this is NOT a possible match. | |
225 | + */ | |
226 | + return getopt_no_match; | |
227 | + | |
228 | + /* DID stop at an `=' internal field separator, | |
229 | + * so this IS a possible match, and what follows is an | |
230 | + * argument to the possibly matched option. | |
231 | + */ | |
232 | + optarg = (char *)(nextchar); | |
233 | + } | |
234 | + return *optname | |
235 | + /* | |
236 | + * if we DIDN'T match the ENTIRE text of the option name, | |
237 | + * then it's a possible abbreviated match ... | |
238 | + */ | |
239 | + ? getopt_abbreviated_match | |
240 | + /* | |
241 | + * but if we DID match the entire option name, | |
242 | + * then it's a DEFINITE EXACT match. | |
243 | + */ | |
244 | + : getopt_exact_match; | |
245 | +} | |
246 | + | |
247 | +static __inline__ | |
248 | +int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind, | |
249 | +struct option *opt, int index, int *retindex, const CHAR *optstring ) | |
250 | +{ | |
251 | + /* Helper function to establish appropriate return conditions, | |
252 | + * on resolution of a long form option. | |
253 | + */ | |
254 | + if( retindex != NULL ) | |
255 | + *retindex = index; | |
256 | + | |
257 | + if( optarg && (opt[index].has_arg == no_argument) ) | |
258 | + /* | |
259 | + * it is an error for the user to specify an option specific argument | |
260 | + * with an option which doesn't expect one! | |
261 | + */ | |
262 | + return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n", | |
263 | + PROGNAME, opt + index, getopt_unknown ); | |
264 | + | |
265 | + else if( (optarg == NULL) && (opt[index].has_arg == required_argument) ) | |
266 | + { | |
267 | + /* similarly, it is an error if no argument is specified | |
268 | + * with an option which requires one ... | |
269 | + */ | |
270 | + if( (*argind + 1) < argc ) | |
271 | + /* | |
272 | + * ... except that the requirement may be satisfied from | |
273 | + * the following comand line argument, if any ... | |
274 | + */ | |
275 | + optarg = argv[++*argind]; | |
276 | + | |
277 | + else | |
278 | + /* so fail this case, only if no such argument exists! | |
279 | + */ | |
280 | + return getopt_argerror( mode, "option `%s%s' requires an argument\n", | |
281 | + PROGNAME, opt + index, getopt_missing_arg( optstring ) ); | |
282 | + } | |
283 | + | |
284 | + /* when the caller has provided a return buffer ... | |
285 | + */ | |
286 | + if( retindex != NULL ) | |
287 | + { | |
288 | + /* ... then we place the proper return value there, | |
289 | + * and return a status code of zero ... | |
290 | + */ | |
291 | + *retindex = opt[index].val; | |
292 | + return 0; | |
293 | + } | |
294 | + /* ... otherwise, the return value becomes the status code. | |
295 | + */ | |
296 | + return opt[index].val; | |
297 | +} | |
298 | + | |
299 | +static | |
300 | +#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring | |
301 | +int getopt_parse( int mode, getopt_std_args, ... ) | |
302 | +{ | |
303 | + /* Common core implementation for ALL `getopt' functions. | |
304 | + */ | |
305 | + static int argind = 0; | |
306 | + static const CHAR *nextchar = NULL; | |
307 | + static int optmark = 0; | |
308 | + | |
309 | + if( nextchar && *nextchar ) | |
310 | + { | |
311 | + /* we are parsing a standard, or short format, option argument ... | |
312 | + */ | |
313 | + const CHAR *optchar; | |
314 | + if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL ) | |
315 | + { | |
316 | + /* we have identified it as valid ... | |
317 | + */ | |
318 | + if( optchar[1] == getopt_takes_argument ) | |
319 | + { | |
320 | + /* and determined that it requires an associated argument ... | |
321 | + */ | |
322 | + if( ! *(optarg = (char *)(nextchar)) ) | |
323 | + { | |
324 | + /* the argument is NOT attached ... | |
325 | + */ | |
326 | + if( optchar[2] == getopt_takes_argument ) | |
327 | + /* | |
328 | + * but this GNU extension marks it as optional, | |
329 | + * so we don't provide one on this occasion. | |
330 | + */ | |
331 | + optarg = NULL; | |
332 | + | |
333 | + /* otherwise this option takes a mandatory argument, | |
334 | + * so, provided there is one available ... | |
335 | + */ | |
336 | + else if( (argc - argind) > 1 ) | |
337 | + /* | |
338 | + * we take the following command line argument, | |
339 | + * as the appropriate option argument. | |
340 | + */ | |
341 | + optarg = argv[++argind]; | |
342 | + | |
343 | + /* but if no further argument is available, | |
344 | + * then there is nothing we can do, except for | |
345 | + * issuing the requisite diagnostic message. | |
346 | + */ | |
347 | + else | |
348 | + { | |
349 | + complain( "option requires an argument -- %c", optopt ); | |
350 | + return getopt_missing_arg( optstring ); | |
351 | + } | |
352 | + } | |
353 | + nextchar = NULL; | |
354 | + } | |
355 | + else | |
356 | + optarg = NULL; | |
357 | + return optopt; | |
358 | + } | |
359 | + /* if we didn't find a valid match for the specified option character, | |
360 | + * then we fall through to here, so take appropriate diagnostic action. | |
361 | + */ | |
362 | + if( mode == getopt_mode_long_only ) | |
363 | + { | |
364 | + complain( "unrecognised option `-%s'", --nextchar ); | |
365 | + nextchar = NULL; | |
366 | + optopt = 0; | |
367 | + } | |
368 | + else complain( "invalid option -- %c", optopt ); | |
369 | + return getopt_unknown; | |
370 | + } | |
371 | + | |
372 | + if( optmark > optind ) | |
373 | + { | |
374 | + /* This can happen, in GNU parsing mode ONLY, when we have | |
375 | + * skipped over non-option arguments, and found a subsequent | |
376 | + * option argument; in this case we permute the arguments. | |
377 | + */ | |
378 | + int index; | |
379 | + /* | |
380 | + * `optspan' specifies the number of contiguous arguments | |
381 | + * which are spanned by the current option, and so must be | |
382 | + * moved together during permutation. | |
383 | + */ | |
384 | + int optspan = argind - optmark + 1; | |
385 | + /* | |
386 | + * we use `this_arg' to store these temporarily. | |
387 | + */ | |
388 | + CHAR *this_arg[optspan]; | |
389 | + /* | |
390 | + * we cannot manipulate `argv' directly, since the `getopt' | |
391 | + * API prototypes it as `read-only'; this cast to `arglist' | |
392 | + * allows us to work around that restriction. | |
393 | + */ | |
394 | + CHAR **arglist = (char **)(argv); | |
395 | + | |
396 | + /* save temporary copies of the arguments which are associated | |
397 | + * with the current option ... | |
398 | + */ | |
399 | + for( index = 0; index < optspan; ++index ) | |
400 | + this_arg[index] = arglist[optmark + index]; | |
401 | + | |
402 | + /* move all preceding non-option arguments to the right, | |
403 | + * overwriting these saved arguments, while making space | |
404 | + * to replace them in their permuted location. | |
405 | + */ | |
406 | + for( --optmark; optmark >= optind; --optmark ) | |
407 | + arglist[optmark + optspan] = arglist[optmark]; | |
408 | + | |
409 | + /* restore the temporarily saved option arguments to | |
410 | + * their permuted location. | |
411 | + */ | |
412 | + for( index = 0; index < optspan; ++index ) | |
413 | + arglist[optind + index] = this_arg[index]; | |
414 | + | |
415 | + /* adjust `optind', to account for the relocated option. | |
416 | + */ | |
417 | + optind += optspan; | |
418 | + } | |
419 | + | |
420 | + else | |
421 | + /* no permutation occurred ... | |
422 | + * simply adjust `optind' for all options parsed so far. | |
423 | + */ | |
424 | + optind = argind + 1; | |
425 | + | |
426 | + /* enter main parsing loop ... | |
427 | + */ | |
428 | + while( argc > ++argind ) | |
429 | + { | |
430 | + /* inspect each argument in turn, identifying possible options ... | |
431 | + */ | |
432 | + if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar ) | |
433 | + { | |
434 | + /* we've found a candidate option argument ... */ | |
435 | + | |
436 | + if( is_switchar( *nextchar ) ) | |
437 | + { | |
438 | + /* it's a double hyphen argument ... */ | |
439 | + | |
440 | + const CHAR *refchar = nextchar; | |
441 | + if( *++refchar ) | |
442 | + { | |
443 | + /* and it looks like a long format option ... | |
444 | + * `getopt_long' mode must be active to accept it as such, | |
445 | + * `getopt_long_only' also qualifies, but we must downgrade | |
446 | + * it to force explicit handling as a long format option. | |
447 | + */ | |
448 | + if( mode >= getopt_mode_long ) | |
449 | + { | |
450 | + nextchar = refchar; | |
451 | + mode = getopt_mode_long; | |
452 | + } | |
453 | + } | |
454 | + else | |
455 | + { | |
456 | + /* this is an explicit `--' end of options marker, so wrap up now! | |
457 | + */ | |
458 | + if( optmark > optind ) | |
459 | + { | |
460 | + /* permuting the argument list as necessary ... | |
461 | + * (note use of `this_arg' and `arglist', as above). | |
462 | + */ | |
463 | + CHAR *this_arg = argv[optmark]; | |
464 | + CHAR **arglist = (CHAR **)(argv); | |
465 | + | |
466 | + /* move all preceding non-option arguments to the right ... | |
467 | + */ | |
468 | + do arglist[optmark] = arglist[optmark - 1]; | |
469 | + while( optmark-- > optind ); | |
470 | + | |
471 | + /* reinstate the `--' marker, in its permuted location. | |
472 | + */ | |
473 | + arglist[optind] = this_arg; | |
474 | + } | |
475 | + /* ... before finally bumping `optind' past the `--' marker, | |
476 | + * and returning the `all done' completion indicator. | |
477 | + */ | |
478 | + ++optind; | |
479 | + return getopt_all_done; | |
480 | + } | |
481 | + } | |
482 | + else if( mode < getopt_mode_long_only ) | |
483 | + { | |
484 | + /* it's not an explicit long option, and `getopt_long_only' isn't active, | |
485 | + * so we must explicitly try to match it as a short option. | |
486 | + */ | |
487 | + mode = getopt_mode_standard; | |
488 | + } | |
489 | + | |
490 | + if( mode >= getopt_mode_long ) | |
491 | + { | |
492 | + /* the current argument is a long form option, (either explicitly, | |
493 | + * introduced by a double hyphen, or implicitly because we were called | |
494 | + * by `getopt_long_only'); this is where we parse it. | |
495 | + */ | |
496 | + int lookup; | |
497 | + int matched = -1; | |
498 | + | |
499 | + /* we need to fetch the `extra' function arguments, which are | |
500 | + * specified for the `getopt_long' APIs. | |
501 | + */ | |
502 | + va_list refptr; | |
503 | + va_start( refptr, optstring ); | |
504 | + struct option *longopts = va_arg( refptr, struct option * ); | |
505 | + int *optindex = va_arg( refptr, int * ); | |
506 | + va_end( refptr ); | |
507 | + | |
508 | + /* ensuring that `optarg' does not inherit any junk, from parsing | |
509 | + * preceding arguments ... | |
510 | + */ | |
511 | + optarg = NULL; | |
512 | + for( lookup = 0; longopts && longopts[lookup].name; ++lookup ) | |
513 | + { | |
514 | + /* scan the list of defined long form options ... | |
515 | + */ | |
516 | + switch( getopt_match_long( nextchar, longopts[lookup].name ) ) | |
517 | + { | |
518 | + /* looking for possible matches for the current argument. | |
519 | + */ | |
520 | + case getopt_exact_match: | |
521 | + /* | |
522 | + * when an exact match is found, | |
523 | + * return it immediately, setting `nextchar' to NULL, | |
524 | + * to ensure we don't mistakenly try to match any | |
525 | + * subsequent characters as short form options. | |
526 | + */ | |
527 | + nextchar = NULL; | |
528 | + return getopt_resolved( mode, argc, argv, &argind, | |
529 | + longopts, lookup, optindex, optstring ); | |
530 | + | |
531 | + case getopt_abbreviated_match: | |
532 | + /* | |
533 | + * but, for a partial (initial substring) match ... | |
534 | + */ | |
535 | + if( matched >= 0 ) | |
536 | + { | |
537 | + /* if this is not the first, then we have an ambiguity ... | |
538 | + */ | |
539 | + complain( "option `%s' is ambiguous", argv[argind] ); | |
540 | + nextchar = NULL; | |
541 | + optopt = 0; | |
542 | + return getopt_unknown; | |
543 | + } | |
544 | + /* otherwise just note that we've found a possible match ... | |
545 | + */ | |
546 | + matched = lookup; | |
547 | + } | |
548 | + } | |
549 | + if( matched >= 0 ) | |
550 | + { | |
551 | + /* if we get to here, then we found exactly one partial match, | |
552 | + * so return it, as for an exact match. | |
553 | + */ | |
554 | + nextchar = NULL; | |
555 | + return getopt_resolved( mode, argc, argv, &argind, | |
556 | + longopts, matched, optindex, optstring ); | |
557 | + } | |
558 | + if( mode < getopt_mode_long_only ) | |
559 | + { | |
560 | + /* if here, then we had what SHOULD have been a long form option, | |
561 | + * but it is unmatched; (perversely, `mode == getopt_mode_long_only' | |
562 | + * allows us to still try to match it as a short form option). | |
563 | + */ | |
564 | + optopt = 0; | |
565 | + nextchar = NULL; | |
566 | + complain( "unrecognised option `%s'", argv[argind] ); | |
567 | + return getopt_unknown; | |
568 | + } | |
569 | + } | |
570 | + /* fall through to handle standard short form options... | |
571 | + * when the option argument format is neither explictly identified | |
572 | + * as long, nor implicitly matched as such, and the argument isn't | |
573 | + * just a bare hyphen, (which isn't an option), then we make one | |
574 | + * recursive call to explicitly interpret it as short format. | |
575 | + */ | |
576 | + if( *nextchar ) | |
577 | + return getopt_parse( mode, argc, argv, optstring ); | |
578 | + } | |
579 | + /* if we get to here, then we've parsed a non-option argument ... | |
580 | + * in GNU compatibility mode, we step over it, so we can permute | |
581 | + * any subsequent option arguments, but ... | |
582 | + */ | |
583 | + if( *optstring == getopt_switchar ) | |
584 | + { | |
585 | + /* if `optstring' begins with a `-' character, this special | |
586 | + * GNU specific behaviour requires us to return the non-option | |
587 | + * arguments in strict order, as pseudo-arguments to a special | |
588 | + * option, with return value defined as `getopt_ordered'. | |
589 | + */ | |
590 | + nextchar = NULL; | |
591 | + optarg = argv[argind]; | |
592 | + return getopt_ordered; | |
593 | + } | |
594 | + if( getopt_conventions( *optstring ) & getopt_posixly_correct ) | |
595 | + /* | |
596 | + * otherwise ... | |
597 | + * for POSIXLY_CORRECT behaviour, or if `optstring' begins with | |
598 | + * a `+' character, then we break out of the parsing loop, so that | |
599 | + * the scan ends at the current argument, with no permutation. | |
600 | + */ | |
601 | + break; | |
602 | + } | |
603 | + /* fall through when all arguments have been evaluated, | |
604 | + */ | |
605 | + return getopt_all_done; | |
606 | +} | |
607 | + | |
608 | +/* All three public API entry points are trivially defined, | |
609 | + * in terms of the internal `getopt_parse' function. | |
610 | + */ | |
611 | +int getopt( getopt_std_args ) | |
612 | +{ | |
613 | + return getopt_parse( getopt_mode_standard, argc, argv, optstring ); | |
614 | +} | |
615 | + | |
616 | +int getopt_long( getopt_std_args, const struct option *opts, int *index ) | |
617 | +{ | |
618 | + return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index ); | |
619 | +} | |
620 | + | |
621 | +int getopt_long_only( getopt_std_args, const struct option *opts, int *index ) | |
622 | +{ | |
623 | + return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index ); | |
624 | +} | |
625 | + | |
626 | +#ifdef __weak_alias | |
627 | +/* | |
628 | + * These Microsnot style uglified aliases are provided for compatibility | |
629 | + * with the previous MinGW implementation of the getopt API. | |
630 | + */ | |
631 | +__weak_alias( getopt, _getopt ) | |
632 | +__weak_alias( getopt_long, _getopt_long ) | |
633 | +__weak_alias( getopt_long_only, _getopt_long_only ) | |
634 | +#endif | |
635 | + | |
636 | +/* $RCSfile$Revision$: end of file */ |
@@ -0,0 +1,100 @@ | ||
1 | +#ifndef __GETOPT_H__ | |
2 | +/* | |
3 | + * getopt.h | |
4 | + * | |
5 | + * $Id$ | |
6 | + * | |
7 | + * Defines constants and function prototypes required to implement | |
8 | + * the `getopt', `getopt_long' and `getopt_long_only' APIs. | |
9 | + * | |
10 | + * This file is part of the MinGW32 package set. | |
11 | + * | |
12 | + * Contributed by Keith Marshall <keithmarshall@users.sourceforge.net> | |
13 | + * Last modification: 04-Jan-2008 | |
14 | + * | |
15 | + * THIS SOFTWARE IS NOT COPYRIGHTED | |
16 | + * | |
17 | + * This source code is offered for use in the public domain. You may | |
18 | + * use, modify or distribute it freely. | |
19 | + * | |
20 | + * This code is distributed in the hope that it will be useful but | |
21 | + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY | |
22 | + * DISCLAIMED. This includes but is not limited to warranties of | |
23 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
24 | + * | |
25 | + * $Revision$ | |
26 | + * $Author$ | |
27 | + * $Date$ | |
28 | + * | |
29 | + */ | |
30 | +#define __GETOPT_H__ | |
31 | + | |
32 | +/* All the headers include this file. */ | |
33 | +#include <_mingw.h> | |
34 | + | |
35 | +#ifdef __cplusplus | |
36 | +extern "C" { | |
37 | +#endif | |
38 | + | |
39 | +extern int optind; /* index of first non-option in argv */ | |
40 | +extern int optopt; /* single option character, as parsed */ | |
41 | +extern int opterr; /* flag to enable built-in diagnostics... */ | |
42 | + /* (user may set to zero, to suppress) */ | |
43 | + | |
44 | +extern char *optarg; /* pointer to argument of current option */ | |
45 | + | |
46 | +extern int getopt( int, char * const [], const char * ); | |
47 | + | |
48 | +#ifdef __cplusplus | |
49 | +} | |
50 | +#endif | |
51 | +/* | |
52 | + * POSIX requires the `getopt' API to be specified in `unistd.h'; | |
53 | + * thus, `unistd.h' includes this header. However, we do not want | |
54 | + * to expose the `getopt_long' or `getopt_long_only' APIs, when | |
55 | + * included in this manner. Thus, close the standard __GETOPT_H__ | |
56 | + * declarations block, and open an additional __GETOPT_LONG_H__ | |
57 | + * specific block, only when *not* __UNISTD_H_SOURCED__, in which | |
58 | + * to declare the extended API. | |
59 | + */ | |
60 | +#endif /* !defined(__GETOPT_H__) */ | |
61 | +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) | |
62 | +#define __GETOPT_LONG_H__ | |
63 | + | |
64 | +#ifdef __cplusplus | |
65 | +extern "C" { | |
66 | +#endif | |
67 | + | |
68 | +struct option /* specification for a long form option... */ | |
69 | +{ | |
70 | + const char *name; /* option name, without leading hyphens */ | |
71 | + int has_arg; /* does it take an argument? */ | |
72 | + int *flag; /* where to save its status, or NULL */ | |
73 | + int val; /* its associated status value */ | |
74 | +}; | |
75 | + | |
76 | +enum /* permitted values for its `has_arg' field... */ | |
77 | +{ | |
78 | + no_argument = 0, /* option never takes an argument */ | |
79 | + required_argument, /* option always requires an argument */ | |
80 | + optional_argument /* option may take an argument */ | |
81 | +}; | |
82 | + | |
83 | +extern int getopt_long( int, char * const [], const char *, const struct option *, int * ); | |
84 | +extern int getopt_long_only( int, char * const [], const char *, const struct option *, int * ); | |
85 | +/* | |
86 | + * Previous MinGW implementation had... | |
87 | + */ | |
88 | +#ifndef HAVE_DECL_GETOPT | |
89 | +/* | |
90 | + * ...for the long form API only; keep this for compatibility. | |
91 | + */ | |
92 | +# define HAVE_DECL_GETOPT 1 | |
93 | +#endif | |
94 | + | |
95 | +#ifdef __cplusplus | |
96 | +} | |
97 | +#endif | |
98 | + | |
99 | +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ | |
100 | +/* $RCSfile$Revision$: end of file */ |