From: mdw Date: Wed, 13 Aug 1997 10:14:31 +0000 (+0000) Subject: Remove common files: use CFD. X-Git-Tag: 1.3.3~123 X-Git-Url: https://git.distorted.org.uk/~mdw/become/commitdiff_plain/2b8c60bcee44ffd039c8c73991455f51ba5e8a30 Remove common files: use CFD. --- diff --git a/COPYING b/COPYING deleted file mode 100644 index 916d1f0..0000000 --- a/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program 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 program 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/aclocal.m4 b/aclocal.m4 deleted file mode 100644 index ae47bf2..0000000 --- a/aclocal.m4 +++ /dev/null @@ -1,60 +0,0 @@ -dnl -*-fundamental-*- -dnl -dnl $Id: aclocal.m4,v 1.2 1997/08/04 10:24:19 mdw Exp $ -dnl -dnl Configuration macros for `become' -dnl -dnl (c) 1997 Mark Wooding -dnl - -dnl----- Licensing notice --------------------------------------------------- -dnl -dnl This file is part of `become' -dnl -dnl `Become' is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 2 of the License, or -dnl (at your option) any later version. -dnl -dnl `Become' is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with `become'; if not, write to the Free Software Foundation, -dnl Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -dnl----- Revision history --------------------------------------------------- -dnl -dnl $Log: aclocal.m4,v $ -dnl Revision 1.2 1997/08/04 10:24:19 mdw -dnl Sources placed under CVS control. -dnl - -dnl MDW_CHECK_MANYLIBS(FUNC, LIBS, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -dnl -dnl Tries to find FUNC in one of the space-separated libraries given in LIBS. -dnl The first one to match is added to the LIBS variable. - -AC_DEFUN(MDW_CHECK_MANYLIBS,[ -AC_CACHE_CHECK([for library containing $1], [mdw_cv_lib_$1], -[mdw_save_LIBS="$LIBS" -mdw_cv_lib_$1="no" -AC_TRY_LINK(,[$1()], [mdw_cv_lib_$1="none required"]) -test "$mdw_cv_lib_$1" = "no" && for i in $2; do -LIBS="-l$i $mdw_save_LIBS" -AC_TRY_LINK(,[$1()], -[mdw_cv_lib_$1="-l$i" -break]) -done -LIBS="$mdw_save_LIBS"]) -if test "$mdw_cv_lib_$1" != "no"; then - test "$mdw_cv_lib_$1" = "none required" || LIBS="$mdw_cv_lib_$1 $LIBS" - $3 -else - : - $4 -fi]) - -dnl----- That's all, folks -------------------------------------------------- diff --git a/install-sh b/install-sh deleted file mode 100755 index 5871924..0000000 --- a/install-sh +++ /dev/null @@ -1,238 +0,0 @@ -#! /bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. -# - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/mkinstalldirs b/mkinstalldirs deleted file mode 100755 index 57a53d5..0000000 --- a/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id: mkinstalldirs,v 1.2 1997/08/04 10:24:24 mdw Exp $ - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" 1>&2 - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/src/mdwopt.c b/src/mdwopt.c deleted file mode 100644 index ad078a5..0000000 --- a/src/mdwopt.c +++ /dev/null @@ -1,771 +0,0 @@ -/* -*-c-*- - * - * $Id: mdwopt.c,v 1.2 1997/08/04 10:24:23 mdw Exp $ - * - * Options parsing, similar to GNU @getopt_long@ - * - * (c) 1996 Mark Wooding - */ - -/*----- Licencing notice --------------------------------------------------* - * - * This file is part of many programs. - * - * `mdwopt' 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. - * - * `mdwopt' 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. - * - * You should have received a copy of the GNU General Public License - * along with `mdwopt'; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/*----- Revision history --------------------------------------------------* - * - * $Log: mdwopt.c,v $ - * Revision 1.2 1997/08/04 10:24:23 mdw - * Sources placed under CVS control. - * - * Revision 1.4 1997/07/29 21:11:35 mdw - * Reformatted. Fixed buffer overflow when dealing with environment - * variables. Included NT in list of daft operating systems with `\' as a - * path separator. Fixed address of the FSF. - * - * Revision 1.3 1997/02/26 00:41:10 mdw - * Added GPL notice to the top. Slight formatting changes. - * - * Revision 1.2 1996/10/28 13:12:13 mdw - * Fixed calls to ctype.h routines. Arguments are cast to unsigned char - * to avoid invoking undefined behaviour caused by signedness of chars. - * - * Revision 1.1 1996/09/24 18:01:28 mdw - * Initial revision - * - */ - -/*----- External dependencies ---------------------------------------------*/ - -#include -#include -#include -#include - -#include "mdwopt.h" - -/*----- Configuration things ----------------------------------------------*/ - -#if defined(__riscos) -# define PATHSEP '.' -#elif defined(__OS2__) || defined(__MSDOS__) || defined(__WINNT__) -# define PATHSEP '\\' -#else /* Assume a sane filing system */ -# define PATHSEP '/' -#endif - -/*----- Global variables --------------------------------------------------*/ - -mdwopt_data mdwopt_global = {0, 0, 0, 1, 0, 0, 0, 0, 0}; - -enum { - ord__permute = 0, /* Permute the options (default) */ - ord__return = 1, /* Return non-option things */ - ord__posix = 2, /* Do POSIX-type hacking */ - ord__negate = 4 /* Magic negate-next-thing flag */ -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mo__nextWord@ --- * - * - * Arguments: @int argc@ = number of command line options - * @char *argv[]@ = pointer to command line options - * @mdwopt_data *data@ = pointer to persistent state - * - * Returns: Pointer to the next word to handle, or 0 - * - * Use: Extracts the next word from the command line or environment - * variable. - */ - -static char *mo__nextWord(int argc, char *const *argv, mdwopt_data *data) -{ - if (data->ind == -1) { - char *p = data->env; - char *q; - while (isspace((unsigned char)*p)) - p++; - q = p; - while (*p && !isspace((unsigned char)*p)) - p++; - *p = 0; - data->env = p + 1; - if (p != q) - return (q); - free(data->estart); - data->env = 0; - data->ind = 1; - } - - if (data->next == argc) - return (0); - return (argv[data->next++]); -} - -/* --- @mo__permute@ --- * - * - * Arguments: @char *argv[]@ = pointer to command line arguments - * @mdwopt_data *data@ = pointer to persistent data - * - * Returns: -- - * - * Use: Moves a command line option into the right place. - */ - -static void mo__permute(char *const *argv, mdwopt_data *data) -{ - char **v = (char **)argv; - if (data->ind != -1) { - int i = data->next - 1; - char *p = v[i]; - while (i > data->ind) { - v[i] = v[i - 1]; - i--; - } - v[i] = p; - data->ind++; - } -} - -/* --- @mo__findOpt@ --- * - * - * Arguments: @int o@ = which option to search for - * @const char *shortopt@ = short options string to search - * @mdwopt_data *data@ = pointer to persistant state - * - * Returns: Pointer to rest of short options string (including magic - * characters) - * - * Use: Looks up a short option in the given string. - */ - -static const char *mo__findOpt(int o, const char *shortopt, - mdwopt_data *data) -{ - const char *p = shortopt; /* Point to short opts table */ - for (;;) { - if (!*p) /* No more options left */ - return (0); - - if (o != *p || (p[1] != '+' && data->order & ord__negate)) { - p++; /* Skip this option entry */ - while (*p == '+') /* Jump a `%|+|%' sign */ - p++; - while (*p == ':') /* And jump any `%|:|%' characters */ - p++; /* Just in case there are any */ - } - else - return (p + 1); - } -} - -/* --- @mdwopt@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char * const *argv@ = pointer to command line arguments - * @const char *shortopt@ = pointer to short options information - * @const struct option *longopts@ = pointer to long opts info - * @int *longind@ = where to store matched longopt - * @mdwopt_data *data@ = persistent state for the parser - * @int flags@ = various useful flags - * - * Returns: Value of option found next, or an error character, or - * @EOF@ for the last thing. - * - * Use: Reads options. The routine should be more-or-less compatible - * with standard getopts, although it provides many more - * features even than the standard GNU implementation. - * - * The precise manner of options parsing is determined by - * various flag settings, which are described below. By setting - * flag values appropriately, you can achieve behaviour very - * similar to most other getopt routines. - * - * - * How options parsing appears to users - * - * A command line consists of a number of `words' (which may - * contain spaces, according to various shell quoting - * conventions). A word may be an option, an argument to an - * option, or a non-option. An option begins with a special - * character, usually `%|-|%', although `%|+|%' is also used - * sometimes. As special exceptions, the word containing only a - * `%|-|%' is considered to be a non-option, since it usually - * represents standard input or output as a filename, and the - * word containing a double-dash `%|--|%' is used to mark all - * following words as being non-options regardless of their - * initial character. - * - * Traditionally, all words after the first non-option have been - * considered to be non-options automatically, so that options - * must be specified before filenames. However, this - * implementation can extract all the options from the command - * line regardless of their position. This can usually be - * disabled by setting one of the environment variables - * `%|POSIXLY_CORRECT|%' or `%|_POSIX_OPTION_ORDER|%'. - * - * There are two different styles of options: `short' and - * `long'. - * - * Short options are the sort which Unix has known for ages: an - * option is a single letter, preceded by a `%|-|%'. Short - * options can be joined together to save space (and possibly to - * make silly words): e.g., instead of giving options - * `%|-x -y|%', a user could write `%|-xy|%'. Some short - * options can have arguments, which appear after the option - * letter, either immediately following, or in the next `word' - * (so an option with an argument could be written as - * `%|-o foo|%' or as `%|-ofoo|%'). Note that options with - * optional arguments must be written in the second style. - * - * When a short option controls a flag setting, it is sometimes - * possible to explicitly turn the flag off, as well as turning - * it on, (usually to override default options). This is - * usually done by using a `%|+|%' instead of a `%|-|%' to - * introduce the option. - * - * Long options, as popularised by the GNU utilities, are given - * long-ish memorable names, preceded by a double-dash `%|--|%'. - * Since their names are more than a single character, long - * options can't be combined in the same way as short options. - * Arguments to long options may be given either in the same - * `word', separated from the option name by an equals sign, or - * in the following `word'. - * - * Long option names can be abbreviated if necessary, as long - * as the abbreviation is unique. This means that options can - * have sensible and memorable names but still not require much - * typing from an experienced user. - * - * Like short options, long options can control flag settings. - * The options to manipulate these settings come in pairs: an - * option of the form `%|--set-flag|%' might set the flag, while - * an option of the form `%|--no-set-flag|%' might clear it. - * - * It is usual for applications to provide both short and long - * options with identical behaviour. Some applications with - * lots of options may only provide long options (although they - * will often be only two or three characters long). In this - * case, long options can be preceded with a single `%|-|%' - * character, and negated by a `%|+|%' character. - * - * Finally, some (older) programs accept arguments of the form - * `%%@.{"-"}%%', to set some numerical parameter, - * typically a line count of some kind. - * - * - * How programs parse options - * - * An application parses its options by calling mdwopt - * repeatedly. Each time it is called, mdwopt returns a value - * describing the option just read, and stores information about - * the option in a data block. The value %$-1$% is returned - * when there are no more options to be read. The `%|?|%' - * character is returned when an error is encountered. - * - * Before starting to parse options, the value @data->ind@ must - * be set to 0 or 1. The value of @data->err@ can also be set, - * to choose whether errors are reported by mdwopt. - * - * The program's `@argc@' and `@argv@' arguments are passed to - * the options parser, so that it can read the command line. A - * flags word is also passed, allowing the program fine control - * over parsing. The flags are described above. - * - * Short options are described by a string, which once upon a - * time just contained the permitted option characters. Now the - * options string begins with a collection of flag characters, - * and various flag characters can be put after options - * characters to change their properties. - * - * If the first character of the short options string is - * `%|+|%', `%|-|%' or `%|!|%', the order in which options are - * read is modified, as follows: - * - * `%|+|%' forces the POSIX order to be used. As soon as a non- - * option is found, mdwopt returns %$-1$%. - * - * `%|-|%' makes mdwopt treat non-options as being `special' - * sorts of option. When a non-option word is found, the - * value 0 is returned, and the actual text of the word - * is stored as being the option's argument. - * - * `%|!|%' forces the default order to be used. The entire - * command line is scanned for options, which are - * returned in order. However, during this process, - * the options are moved in the @argv@ array, so that - * they appear before the non- options. - * - * A `%|:|%' character may be placed after the ordering flag (or - * at the very beginning if no ordering flag is given) which - * indicates that the character `%|:|%', rather than `%|?|%', - * should be returned if a missing argument error is detected. - * - * Each option in the string can be followed by a `%|+|%' sign, - * indicating that it can be negated, a `%|:|%' sign indicating - * that it requires an argument, or a `%|::|%' string, - * indicating an optional argument. Both `%|+|%' and `%|:|%' or - * `%|::|%' may be given, although the `%|+|%' must come first. - * - * If an option is found, the option character is returned to - * the caller. A pointer to an argument is stored in - * @data->arg@, or @NULL@ is stored if there was no argument. - * If a negated option was found, the option character is - * returned ORred with @gFlag_negated@ (bit 8 set). - * - * Long options are described in a table. Each entry in the - * table is of type @struct option@, and the table is terminated - * by an entry whose @name@ field is null. Each option has - * a flags word which, due to historical reasons, is called - * @has_arg@. This describes various properties of the option, - * such as what sort of argument it takes, and whether it can - * be negated. - * - * When mdwopt finds a long option, it looks the name up in the - * table. The index of the matching entry is stored in the - * @longind@ variable, passed to mdwopt (unless @longind@ is 0): - * a value of %$-1$% indicates that no long option was - * found. The behaviour is then dependent on the values in the - * table entry. If @flag@ is nonzero, it points to an integer - * to be modified by mdwopt. Usually the value in the @val@ - * field is simply stored in the @flag@ variable. If the flag - * @gFlag_switch@ is set, however, the value is combined with - * the existing value of the flags using a bitwise OR. If - * @gFlag_negate@ is set, then the flag bit will be cleared if a - * matching negated long option is found. The value 0 is - * returned. - * - * If @flag@ is zero, the value in @val@ is returned by mdwopt, - * possibly with bit 8 set if the option was negated. - * - * Arguments for long options are stored in @data->arg@, as - * before. - * - * Numeric options, if enabled, cause the value `%|#|%' to be - * returned, and the numeric value to be stored in @data->opt@. - * - * If the flag @gFlag_envVar@ is set on entry, options will be - * extracted from an environment variable whose name is built by - * capitalising all the letters of the program's name. (This - * allows a user to have different default settings for a - * program, by calling it through different symbolic links.) */ - -int mdwopt(int argc, char *const *argv, - const char *shortopt, - const struct option *longopts, int *longind, - mdwopt_data *data, int flags) -{ - /* --- Local variables --- */ - - char *p, *q, *r; /* Some useful things to have */ - char *prefix; /* Prefix from this option */ - int i; /* Always useful */ - char noarg = '?'; /* Standard missing-arg char */ - - /* --- Sort out our data --- */ - - if (!data) /* If default data requested */ - data = &mdwopt_global; /* Then use the global stuff */ - - /* --- See if this is the first time --- */ - - if (data->ind == 0 || (data->ind == 1 && ~flags & gFlag_noProgName)) { - - /* --- Sort out default returning order --- */ - - if (getenv("_POSIX_OPTION_ORDER") || /* Examine environment for opts */ - getenv("POSIXLY_CORRECT")) /* To see if we disable features */ - data->order = ord__posix; /* If set, use POSIX ordering */ - else - data->order = ord__permute; /* Otherwise mangle the options */ - - /* --- Now see what the caller actually wants --- */ - - switch (shortopt[0]) { /* Look at the first character */ - case '-': /* `%|-|%' turns on in-orderness */ - data->order = ord__return; - break; - case '+': /* `%|+|%' turns on POSIXness */ - data->order = ord__posix; - break; - case '!': /* `%|!|%' ignores POSIXness */ - data->order = ord__permute; - break; - } - - /* --- Now decide on the program's name --- */ - - if (~flags & gFlag_noProgName) { - p = q = (char *)argv[0]; - while (*p) { - if (*p++ == PATHSEP) - q = p; - } - data->prog = q; - - data->ind = data->next = 1; - data->list = 0; - - /* --- See about environment variables --- * - * - * Be careful. The program may be setuid, and an attacker might have - * given us a long name in @argv[0]@. If the name is very long, don't - * support this option. - */ - - if (flags & gFlag_envVar && strlen(data->prog) < 48) { - - char buf[64]; - - /* --- For RISC OS, support a different format --- * - * - * Acorn's RISC OS tends to put settings in variables named - * `App$Options' rather than `APP'. Under RISC OS, I'll support - * both methods, just to avoid confuddlement. - */ - -#ifdef __riscos - sprintf(buf, "%s$Options", data->prog); - p = getenv(buf); - if (!p) { -#endif - - p = buf; /* Point to a buffer */ - q = data->prog; /* Point to program name */ - while (*q) /* While characters left here */ - *p++ = toupper(*q++); /* Copy and uppercase */ - *p++ = 0; /* Terminate my copy of this */ - p = getenv(buf); /* Get the value of the variable */ - -#ifdef __riscos - } -#endif - - /* --- Copy the options string into a buffer --- */ - - if (p) { /* If it is defined */ - q = malloc(strlen(p) + 1); /* Allocate space for a copy */ - if (!q) { /* If that failed */ - fprintf(stderr, /* Report a nice error */ - "%s: Not enough memory to read settings in " - "environment variable\n", - data->prog); - } else { /* Otherwise */ - strcpy(q, p); /* Copy the text over */ - data->ind = -1; /* Mark that we're parsing envvar */ - data->env = data->estart = q; /* And store the pointer away */ - } - } - - } - } - else - data->ind = data->next = 0; - } - - /* --- Do some initial bodgery --- * - * - * The @shortopt@ string can have some interesting characters at the - * beginning. We'll skip past them. - */ - - switch (shortopt[0]) { - case '+': - case '-': - case '!': - shortopt++; - break; - } - - if (shortopt[0] == ':') { - noarg = shortopt[0]; - shortopt++; - } - - if (longind) /* Allow longind to be null */ - *longind = -1; /* Clear this to avoid confusion */ - data->opt = -1; /* And this too */ - data->arg = 0; /* No option set up here */ - - /* --- Now go off and search for an option --- */ - - if (!data->list || !*data->list) { - data->order &= 3; /* Clear negation flag */ - - /* --- Now we need to find the next option --- * - * - * Exactly how we do this depends on the settings of the order variable. - * We identify options as being things starting with `%|-|%', and which - * aren't equal to `%|-|%' or `%|--|%'. We'll look for options until: - * - * * We find something which isn't an option AND @order == ord__posix@ - * * We find a `%|--|%' - * * We reach the end of the list - * - * There are some added little wrinkles, which we'll meet as we go. - */ - - for (;;) { /* Keep looping for a while */ - p = mo__nextWord(argc, argv, data); /* Get the next word out */ - if (!p) /* If there's no next word */ - return (EOF); /* There's no more now */ - - /* --- See if we've found an option --- */ - - if ((p[0] == '-' || (p[0] == '+' && flags & gFlag_negation)) && - p[1] != 0) { - if (strcmp(p, "--") == 0) { /* If this is the magic marker */ - mo__permute(argv, data); /* Stow the magic marker item */ - return (EOF); /* There's nothing else to do */ - } - break; /* We've found something! */ - } - - /* --- Figure out how to proceed --- */ - - switch (data->order & 3) { - case ord__posix: /* POSIX option order */ - return (EOF); /* This is easy */ - break; - case ord__permute: /* Permute the option order */ - break; - case ord__return: /* Return each argument */ - mo__permute(argv, data); /* Insert word in same place */ - data->arg = p; /* Point to the argument */ - return (0); /* Return the value */ - } - } - - /* --- We found an option --- */ - - mo__permute(argv, data); /* Do any permuting necessary */ - - /* --- Check for a numeric option --- * - * - * We only check the first character (or the second if the first is a - * sign). This ought to be enough. - */ - - if (flags & gFlag_numbers && (p[0] == '-' || flags & gFlag_negNumber)) { - if (((p[1] == '+' || p[1] == '-') && isdigit((unsigned char)p[2])) || - isdigit((unsigned char)p[1])) { - data->opt = strtol(p + 1, &data->arg, 10); - while (isspace((unsigned char)data->arg[0])) - data->arg++; - if (!data->arg[0]) - data->arg = 0; - return (p[0] == '-' ? '#' : '#' | gFlag_negated); - } - } - - /* --- Check for a long option --- */ - - if (p[0] == '+') - data->order |= ord__negate; - - if (((p[0] == '-' && p[1] == '-') || - (flags & gFlag_noShorts && !mo__findOpt(p[1], shortopt, data))) && - (~flags & gFlag_noLongs)) /* Is this a long option? */ - { - int match = -1; /* Count matches as we go */ - - if (p[0] == '+') { /* If it's negated */ - data->order |= ord__negate; /* Set the negate flag */ - p++; /* Point to the main text */ - prefix = "+"; /* Set the prefix string up */ - } else if (p[1] == '-') { /* If this is a `%|--|%' option */ - if ((flags & gFlag_negation) && strncmp(p + 2, "no-", 3) == 0) { - p += 5; /* Point to main text */ - prefix = "--no-"; /* And set the prefix */ - data->order |= ord__negate; /* Set the negatedness flag */ - } else { - p += 2; /* Point to the main text */ - prefix = "--"; /* Remember the prefix string */ - } - } else { - if ((flags & gFlag_negation) && strncmp(p + 1, "no-", 3) == 0) { - p += 4; /* Find the text */ - prefix = "-no-"; /* Set the prefix */ - data->order |= ord__negate; /* Set negatedness flag */ - } else { - p++; /* Otherwise find the text */ - prefix = "-"; /* And remember the prefix */ - } - } - - for (i = 0; longopts[i].name; i++) { /* Loop through the options */ - if ((data->order & ord__negate) && - (~longopts[i].has_arg & gFlag_negate)) - continue; /* If neg and opt doesn't allow */ - - r = (char *) longopts[i].name; /* Point to the name string */ - q = p; /* Point to the string start */ - for (;;) { /* Do a loop here */ - if (*q == 0 || *q == '=') { /* End of the option string? */ - if (*r == 0) { /* If end of other string */ - match = i; /* This is the match */ - goto botched; /* And exit the loop now */ - } - if (match == -1) { /* If no match currently */ - match = i; /* Then this is it, here */ - break; /* Stop looking now */ - } else { - match = -1; /* Else it's ambiguous */ - goto botched; /* So give up right now */ - } - } - else if (*q != *r) /* Otherwise if mismatch */ - break; /* Abort this loop */ - q++, r++; /* Increment the counters */ - } - } - - botched: - if (match == -1) { /* If we couldn't find a match */ - if (data->err) { - fprintf(stderr, "%s: unrecognised option `%s%s'\n", - data->prog, - prefix, p); - } - return ('?'); - } - - if (longind) /* Allow longind to be null */ - *longind = match; /* Store the match away */ - - /* --- Handle argument behaviour --- */ - - while (*p != 0 && *p != '=') /* Find the argument string */ - p++; - p = (*p ? p + 1 : 0); /* Sort out argument presence */ - q = (char *) longopts[match].name; /* Remember the name here */ - - switch (longopts[match].has_arg & 3) { - case no_argument: - if (p) { - if (data->err) { - fprintf(stderr, - "%s: option `%s%s' does not accept arguments\n", - data->prog, - prefix, q); - } - return ('?'); - } - break; - - case required_argument: - if (!p) { /* If no argument given */ - p = mo__nextWord(argc, argv, data); - - if (!p) { /* If no more arguments */ - if (data->err) { - fprintf(stderr, "%s: option `%s%s' requires an argument\n", - data->prog, - prefix, q); - } - return (noarg); - } - - mo__permute(argv, data); - } - break; - - case optional_argument: - /* Who cares? */ - break; - } - data->arg = p; - - /* --- Do correct things now we have a match --- */ - - if (longopts[match].flag) { /* If he has a @flag@ argument */ - if (longopts[match].has_arg & gFlag_switch) { - if (data->order & ord__negate) - *longopts[match].flag &= ~longopts[match].val; - else - *longopts[match].flag |= longopts[match].val; - } else { - if (data->order & ord__negate) - *longopts[match].flag = 0; - else - *longopts[match].flag = longopts[match].val; - } - return (0); /* And return something */ - } else { - if (data->order & ord__negate) - return (longopts[match].val | gFlag_negated); - else - return (longopts[match].val); - } - } - - /* --- Do short options things --- */ - - else { - if (p[0] == '+') /* If starts with a `%|+|%' */ - data->order |= ord__negate; - data->list = p + 1; /* Omit leading `%|-|%'/`%|+|%' */ - } - } - - /* --- Now process the short options --- */ - - i = *data->list++; /* Get the next option letter */ - data->opt = i; /* Store this away nicely */ - - p = (char *) mo__findOpt(i, shortopt, data); - if (!p) { /* No more options left */ - if (data->err) { - fprintf(stderr, "%s: unknown option `%c%c'\n", - data->prog, - data->order & ord__negate ? '+' : '-', - i); - } - return ('?'); - } - - data->opt = i; /* Store this for the caller */ - - /* --- Sort out an argument, if we expect one --- */ - - if (p[0] == ':') { /* If we expect an option */ - q = (data->list[0] ? data->list : 0); /* If argument expected, use it */ - data->list = 0; /* Kill the remaining options */ - if (p[1] != ':' && !q) { /* If no arg, and not optional */ - - /* --- Same code as before --- */ - - q = mo__nextWord(argc, argv, data); /* Read the next word */ - if (!q) { /* If no more arguments */ - if (data->err) { - fprintf(stderr, "%s: option `%c%c' requires an argument\n", - data->prog, - data->order & ord__negate ? '+' : '-', - i); - } - return (noarg); - } - mo__permute(argv, data); - } - - data->arg = q; - } - return ((data->order & ord__negate) ? i | gFlag_negated : i); -} - -/*----- That's all, folks -------------------------------------------------*/ diff --git a/src/mdwopt.h b/src/mdwopt.h deleted file mode 100644 index 78087d6..0000000 --- a/src/mdwopt.h +++ /dev/null @@ -1,420 +0,0 @@ -/* -*-c-*- - * - * $Id: mdwopt.h,v 1.2 1997/08/04 10:24:24 mdw Exp $ - * - * Options parsing, similar to GNU @getopt_long@ - * - * (c) 1996 Mark Wooding - */ - -/*----- Licencing notice --------------------------------------------------* - * - * This file is part of many programs. - * - * `mdwopt' 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. - * - * `mdwopt' 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. - * - * You should have received a copy of the GNU General Public License - * along with `mdwopt'; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/*----- Revision history --------------------------------------------------* - * - * $Log: mdwopt.h,v $ - * Revision 1.2 1997/08/04 10:24:24 mdw - * Sources placed under CVS control. - * - * Revision 1.4 1997/07/29 21:11:49 mdw - * Fixed address of the FSF. - * - * Revision 1.3 1996/12/31 19:41:33 mdw - * Formatting changes. - * - * Revision 1.2 1996/11/23 00:47:25 mdw - * Added `MdwOpt' object from the `anagram' source code. - * - * Revision 1.1 1996/09/24 18:01:43 mdw - * Initial revision - * - */ - -#ifndef MDWOPT_H -#define MDWOPT_H - -/*----- Options handling structures ---------------------------------------*/ - -#ifdef __cplusplus - extern "C" { -#endif - -/* --- @mdwopt_data@ --- * - * - * Contains all the information needed by the @mdwopt@ routine to do its - * work. - */ - -typedef struct { - /* --- Public variables --- */ - - char *arg; /* Arg of current option, or 0 */ - int opt; /* Value of current option */ - int ind; /* 0 for init, index when done */ - int err; /* Set nonzero for error messages */ - char *prog; /* Program name (from @argv[0]@) */ - - /* --- Private variables --- * - * - * Don't play with these, please. - */ - - char *list; /* Current short options pointer */ - int next; /* Next argument, unpermuted */ - int order; /* Ordering of options, flags */ - char *env; /* Where we are in the env var */ - char *estart; /* Pointer to env var buffer */ -} -mdwopt_data; - -/*----- Global variables --------------------------------------------------*/ - -extern mdwopt_data mdwopt_global; /* The default global data */ - -/* --- For compatibility with older programs (and prettiness) --- * - * - * The macros here access the global structure defined above. I consider it - * to be perfectly acceptable to use these macros in new code, because it - * looks nicer than playing with @mdwopt_global@. - */ - -#define optarg (mdwopt_global.arg) /* Argument of current option */ -#define optopt (mdwopt_global.opt) /* Code of current option */ -#define opterr (mdwopt_global.err) /* Zero to report error messages */ -#define optind (mdwopt_global.ind) /* Index of first non-option */ -#define optprog (mdwopt_global.prog) /* Pointer to program name */ - -/*----- Type definitions --------------------------------------------------*/ - -/* --- Long options definition table --- */ - -struct option { - const char *name; /* Name of the long option */ - int has_arg; /* Does it have an argument? */ - int *flag; /* Address of flag variable */ - int val; /* Value to store/return */ -}; - -/* --- Old-style names for argument flags in long options table --- */ - -enum { - no_argument, /* No argument required */ - required_argument, /* User must specify argument */ - optional_argument /* Argument is optional */ -}; - -/* --- New style flag names --- */ - -enum { - gFlag_argReq = 1, /* Required argument */ - gFlag_argOpt = 2, /* Optional argument */ - gFlag_switch = 4, /* OR val into flag, don't store */ - gFlag_negate = 8, /* Allow long option to be negated */ - gFlag__last_long_opt_flag = 0 /* Dummy value */ -}; - -enum { - gFlag_noLongs = 1, /* Don't read long options */ - gFlag_noShorts = 2, /* Don't read short options */ - gFlag_numbers = 4, /* Read numeric options */ - gFlag_negation = 8, /* Allow `%|+|%' for negations */ - gFlag_envVar = 16, /* Parse options from env var */ - gFlag_noProgName = 32, /* Don't set @optprog@ */ - gFlag_negNumber = 64, /* Allow negated number options */ - gFlag__last_mdwopt_flag = 0 /* Dummy value */ -}; - -enum { - gFlag_negated = 256, /* Option flag was negated by user */ - gFlag__last_return_flag = 0 /* Dummy value */ -}; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @mdwopt@ --- * - * - * Arguments: @int argc@ = number of command line arguments - * @char * const *argv@ = pointer to command line arguments - * @const char *shortopt@ = pointer to short options information - * @const struct option *longopts@ = pointer to long opts info - * @int *longind@ = where to store matched longopt - * @mdwopt_data *data@ = persistent state for the parser - * @int flags@ = various useful flags - * - * Returns: Value of option found next, or an error character, or - * @EOF@ for the last thing. - * - * Use: Reads options. The routine should be more-or-less compatible - * with standard getopts, although it provides many more - * features even than the standard GNU implementation. - * - * The precise manner of options parsing is determined by - * various flag settings, which are described below. By setting - * flag values appropriately, you can achieve behaviour very - * similar to most other getopt routines. - * - * - * How options parsing appears to users - * - * A command line consists of a number of `words' (which may - * contain spaces, according to various shell quoting - * conventions). A word may be an option, an argument to an - * option, or a non-option. An option begins with a special - * character, usually `%|-|%', although `%|+|%' is also used - * sometimes. As special exceptions, the word containing only a - * `%|-|%' is considered to be a non-option, since it usually - * represents standard input or output as a filename, and the - * word containing a double-dash `%|--|%' is used to mark all - * following words as being non-options regardless of their - * initial character. - * - * Traditionally, all words after the first non-option have been - * considered to be non-options automatically, so that options - * must be specified before filenames. However, this - * implementation can extract all the options from the command - * line regardless of their position. This can usually be - * disabled by setting one of the environment variables - * `%|POSIXLY_CORRECT|%' or `%|_POSIX_OPTION_ORDER|%'. - * - * There are two different styles of options: `short' and - * `long'. - * - * Short options are the sort which Unix has known for ages: an - * option is a single letter, preceded by a `%|-|%'. Short - * options can be joined together to save space (and possibly to - * make silly words): e.g., instead of giving options - * `%|-x.-y|%', a user could write `%|-xy|%'. Some short - * options can have arguments, which appear after the option - * letter, either immediately following, or in the next `word' - * (so an option with an argument could be written as - * `%|-o foo|%' or as `%|-ofoo|%'). Note that options with - * optional arguments must be written in the second style. - * - * When a short option controls a flag setting, it is sometimes - * possible to explicitly turn the flag off, as well as turning - * it on, (usually to override default options). This is - * usually done by using a `%|+|%' instead of a `%|-|%' to - * introduce the option. - * - * Long options, as popularised by the GNU utilities, are given - * long-ish memorable names, preceded by a double-dash `%|--|%'. - * Since their names are more than a single character, long - * options can't be combined in the same way as short options. - * Arguments to long options may be given either in the same - * `word', separated from the option name by an equals sign, or - * in the following `word'. - * - * Long option names can be abbreviated if necessary, as long - * as the abbreviation is unique. This means that options can - * have sensible and memorable names but still not require much - * typing from an experienced user. - * - * Like short options, long options can control flag settings. - * The options to manipulate these settings come in pairs: an - * option of the form `%|--set-flag|%' might set the flag, while - * an option of the form `%|--no-set-flag|%' might clear it. - * - * It is usual for applications to provide both short and long - * options with identical behaviour. Some applications with - * lots of options may only provide long options (although they - * will often be only two or three characters long). In this - * case, long options can be preceded with a single `%|-|%' - * character, and negated by a `%|+|%' character. - * - * Finally, some (older) programs accept arguments of the form - * `%%@.{"-"}%%', to set some numerical parameter, - * typically a line count of some kind. - * - * - * How programs parse options - * - * An application parses its options by calling mdwopt - * repeatedly. Each time it is called, mdwopt returns a value - * describing the option just read, and stores information about - * the option in a data block. The value %$-1$% is returned - * when there are no more options to be read. The `%|?|%' - * character is returned when an error is encountered. - * - * Before starting to parse options, the value @data->ind@ must - * be set to 0 or 1. The value of @data->err@ can also be set, - * to choose whether errors are reported by mdwopt. - * - * The program's `@argc@' and `@argv@' arguments are passed to - * the options parser, so that it can read the command line. A - * flags word is also passed, allowing the program fine control - * over parsing. The flags are described above. - * - * Short options are described by a string, which once upon a - * time just contained the permitted option characters. Now the - * options string begins with a collection of flag characters, - * and various flag characters can be put after options - * characters to change their properties. - * - * If the first character of the short options string is - * `%|+|%', `%|-|%' or `%|!|%', the order in which options are - * read is modified, as follows: - * - * `%|+|%' forces the POSIX order to be used. As soon as a non- - * option is found, mdwopt returns %$-1$%. - * - * `%|-|%' makes mdwopt treat non-options as being `special' - * sorts of option. When a non-option word is found, the - * value 0 is returned, and the actual text of the word - * is stored as being the option's argument. - * - * `%|!|%' forces the default order to be used. The entire - * command line is scanned for options, which are - * returned in order. However, during this process, - * the options are moved in the @argv@ array, so that - * they appear before the non- options. - * - * A `%|:|%' character may be placed after the ordering flag (or - * at the very beginning if no ordering flag is given) which - * indicates that the character `%|:|%', rather than `%|?|%', - * should be returned if a missing argument error is detected. - * - * Each option in the string can be followed by a `%|+|%' sign, - * indicating that it can be negated, a `%|:|%' sign indicating - * that it requires an argument, or a `%|::|%' string, - * indicating an optional argument. Both `%|+|%' and `%|:|%' or - * `%|::|%' may be given, although the `%|+|%' must come first. - * - * If an option is found, the option character is returned to - * the caller. A pointer to an argument is stored in - * @data->arg@, or @NULL@ is stored if there was no argument. - * If a negated option was found, the option character is - * returned ORred with @gFlag_negated@ (bit 8 set). - * - * Long options are described in a table. Each entry in the - * table is of type @struct option@, and the table is terminated - * by an entry whose @name@ field is null. Each option has - * a flags word which, due to historical reasons, is called - * @has_arg@. This describes various properties of the option, - * such as what sort of argument it takes, and whether it can - * be negated. - * - * When mdwopt finds a long option, it looks the name up in the - * table. The index of the matching entry is stored in the - * @longind@ variable, passed to mdwopt (unless @longind@ is 0): - * a value of %$-1$% indicates that no long option was - * found. The behaviour is then dependent on the values in the - * table entry. If @flag@ is nonzero, it points to an integer - * to be modified by mdwopt. Usually the value in the @val@ - * field is simply stored in the @flag@ variable. If the flag - * @gFlag_switch@ is set, however, the value is combined with - * the existing value of the flags using a bitwise OR. If - * @gFlag_negate@ is set, then the flag bit will be cleared if a - * matching negated long option is found. The value 0 is - * returned. - * - * If @flag@ is zero, the value in @val@ is returned by mdwopt, - * possibly with bit 8 set if the option was negated. - * - * Arguments for long options are stored in @data->arg@, as - * before. - * - * Numeric options, if enabled, cause the value `%|#|%' to be - * returned, and the numeric value to be stored in @data->opt@. - * - * If the flag @gFlag_envVar@ is set on entry, options will be - * extracted from an environment variable whose name is built by - * capitalising all the letters of the program's name. (This - * allows a user to have different default settings for a - * program, by calling it through different symbolic links.) */ - -extern int mdwopt(int /*argc*/, char *const */*argv*/, - const char */*shortopt*/, - const struct option */*longopts*/, int */*longind*/, - mdwopt_data */*data*/, int /*flags*/); - -/* --- Macros for more commonly used routines --- */ - -#define getopt(c, v, o) mdwopt(c, v, o, 0, 0, 0, gFlag_noLongs) -#define getopt_long(c, v, o, l, li) mdwopt(c, v, o, l, li, 0, 0) -#define getopt_long_only(c, v, o, l, li) \ - mdwopt(c, v, o, l, li, 0, gFlag_noShorts) - -#ifdef __cplusplus -} -#endif - -/*----- C++ wrapper class -------------------------------------------------*/ - -#ifdef __cplusplus - -/* --- Class: @MdwOpt@ --- * - * - * Parent: --- - * - * Methods: @MdwOpt@ -- construct a new mdwopt object with the given - * arguments. These are remembered for later use. - * @arg@ -- return the argument of the current option - * arguments. These are remembered for later use. - * @arg@ -- return the argument of the current option - * @opt@ -- return the value of the current option - * @ind@ -- return the index of the next unread argument - * @longind@ -- return index of current long option in table - * @errors@ -- return or set whether we report errors to the - * user - * @prog@ -- return program name from @argv[0]@ - * @next@ -- return next option read from the table - * - * Use: A simple C++ class for encapsulating the options parser. - * The methods are all nice and simple, and extremely similar - * to the normal C interface described above. - */ - -class MdwOpt { - protected: - int argc; - char * const *argv; - const char *shortopts; - const struct option *longopts; - int long_ind; - int flags; - - mdwopt_data data; - - public: - MdwOpt(int c, char * const *v, const char *so, - const struct option *lo, int f=0) : - argc(c), argv(v), shortopts(so), longopts(lo), flags(f) { - data.ind = 0; - data.err = 1; - } - - const char *arg(void) const { return (data.arg); } - int opt(void) const { return (data.opt); } - int errors(void) const { return (data.err); } - int errors(int e) { int oe = data.err; data.err = e; return (oe); } - int ind(void) const { return (data.ind); } - int longind(void) const { return (long_ind); } - const char *prog(void) const { return (data.prog); } - - int next(void) { - return (mdwopt(argc, argv, shortopts, - longopts, &long_ind, &data, flags)); - } -}; - -#endif - -/*----- That's all, folks -------------------------------------------------*/ - -#endif