]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
New sntp/libopts/
authorHarlan Stenn <stenn@ntp.org>
Fri, 26 Aug 2005 08:17:32 +0000 (04:17 -0400)
committerHarlan Stenn <stenn@ntp.org>
Fri, 26 Aug 2005 08:17:32 +0000 (04:17 -0400)
bk: 430ed01ccCFeGaDCpTAGZ-Fjp-F-Sg

36 files changed:
sntp/libopts/COPYING.lgpl [new file with mode: 0644]
sntp/libopts/COPYING.mbsd [new file with mode: 0644]
sntp/libopts/MakeDefs.inc [new file with mode: 0644]
sntp/libopts/Makefile.am [new file with mode: 0644]
sntp/libopts/README [new file with mode: 0644]
sntp/libopts/autoopts.c [new file with mode: 0644]
sntp/libopts/autoopts.h [new file with mode: 0644]
sntp/libopts/autoopts/options.h [new file with mode: 0644]
sntp/libopts/autoopts/usage-txt.h [new file with mode: 0644]
sntp/libopts/boolean.c [new file with mode: 0644]
sntp/libopts/compat/compat.h [new file with mode: 0644]
sntp/libopts/compat/pathfind.c [new file with mode: 0644]
sntp/libopts/configfile.c [new file with mode: 0644]
sntp/libopts/cook.c [new file with mode: 0644]
sntp/libopts/enumeration.c [new file with mode: 0644]
sntp/libopts/environment.c [new file with mode: 0644]
sntp/libopts/genshell.c [new file with mode: 0644]
sntp/libopts/genshell.h [new file with mode: 0644]
sntp/libopts/libopts.c [new file with mode: 0644]
sntp/libopts/libopts.m4 [new file with mode: 0644]
sntp/libopts/load.c [new file with mode: 0644]
sntp/libopts/makeshell.c [new file with mode: 0644]
sntp/libopts/nested.c [new file with mode: 0644]
sntp/libopts/numeric.c [new file with mode: 0644]
sntp/libopts/pgusage.c [new file with mode: 0644]
sntp/libopts/proto.h [new file with mode: 0644]
sntp/libopts/putshell.c [new file with mode: 0644]
sntp/libopts/restore.c [new file with mode: 0644]
sntp/libopts/save.c [new file with mode: 0644]
sntp/libopts/sort.c [new file with mode: 0644]
sntp/libopts/stack.c [new file with mode: 0644]
sntp/libopts/streqvcmp.c [new file with mode: 0644]
sntp/libopts/text_mmap.c [new file with mode: 0644]
sntp/libopts/tokenize.c [new file with mode: 0644]
sntp/libopts/usage.c [new file with mode: 0644]
sntp/libopts/version.c [new file with mode: 0644]

diff --git a/sntp/libopts/COPYING.lgpl b/sntp/libopts/COPYING.lgpl
new file mode 100644 (file)
index 0000000..52f31fd
--- /dev/null
@@ -0,0 +1,502 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, 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 library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+  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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+  If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be 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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+  9. 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 Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+  11. 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 Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  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.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/sntp/libopts/COPYING.mbsd b/sntp/libopts/COPYING.mbsd
new file mode 100644 (file)
index 0000000..8a70427
--- /dev/null
@@ -0,0 +1,26 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+
+    3. The name of the author may not be used to endorse or promote
+       products derived from this software without specific prior
+       written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/sntp/libopts/MakeDefs.inc b/sntp/libopts/MakeDefs.inc
new file mode 100644 (file)
index 0000000..952327d
--- /dev/null
@@ -0,0 +1,5 @@
+if NEED_LIBOPTS
+LIBOPTS_DIR = libopts
+else
+LIBOPTS_DIR =
+endif
diff --git a/sntp/libopts/Makefile.am b/sntp/libopts/Makefile.am
new file mode 100644 (file)
index 0000000..1b820cb
--- /dev/null
@@ -0,0 +1,19 @@
+## LIBOPTS Makefile
+MAINTAINERCLEANFILES  = Makefile.in
+lib_LTLIBRARIES       = libopts.la
+libopts_la_SOURCES    = libopts.c
+libopts_la_CPPFLAGS   = -I$(top_srcdir)
+libopts_la_LDFLAGS    = -version-info  25:2:0
+EXTRA_DIST            = \
+    COPYING.lgpl         COPYING.mbsd         MakeDefs.inc  \
+    README               autoopts/options.h   autoopts/usage-txt.h  \
+    autoopts.c           autoopts.h           boolean.c  \
+    compat/pathfind.c    compat/compat.h      configfile.c  \
+    cook.c               enumeration.c        environment.c  \
+    genshell.c           genshell.h           libopts.m4  \
+    load.c               makeshell.c          nested.c  \
+    numeric.c            pgusage.c            proto.h  \
+    putshell.c           restore.c            save.c  \
+    sort.c               stack.c              streqvcmp.c  \
+    text_mmap.c          tokenize.c           usage.c  \
+    version.c
diff --git a/sntp/libopts/README b/sntp/libopts/README
new file mode 100644 (file)
index 0000000..a55d79c
--- /dev/null
@@ -0,0 +1,89 @@
+        THIS TARBALL IS NOT A FULL DISTRIBUTION.
+
+The contents of this tarball is designed to be incorporated into
+software packages that utilize the AutoOpts option automation
+package and are intended to be installed on systems that may not
+have libopts installed.
+
+Usage Instructions for autoconf/automake/libtoolized projects:
+
+1. Install the unrolled tarball into your package source tree,
+   copying ``libopts.m4'' to your autoconf macro directory.
+
+   In your bootstrap (pre-configure) script, you can do this:
+
+      rm -rf libopts libopts-*
+      gunzip -c `autoopts-config libsrc` | tar -xvf -
+      mv -f libopts-*.*.* libopts
+      cp -fp libopts/libopts.m4 config/.
+
+   I tend to put my configure auxiliary files in "config".
+   Whatever directory you choose, if it is not ".", then
+   be sure to tell autoconf about it with:
+
+      AC_CONFIG_AUX_DIR(config)
+
+   This is one macro where you *MUST* remember to *NOT* quote
+   the argument.  If you do, automake will get lost.
+
+2. Add the following to your ``configure.ac'' file:
+
+      LIBOPTS_CHECK
+
+   This macro will automatically invoke
+
+      AC_CONFIG_FILES( [libopts/Makefile] )
+
+3. Add the following to your top level ``Makefile.am'' file:
+
+      include $(srcdir)/libopts/MakeDefs.inc
+      if NEED_LIBOPTS
+         SUBDIRS = <...> libopts <...>
+         <<Makefile.am text for when building libopts>>
+      else
+         SUBDIRS = <...>
+         <<Makefile.am text for when libopts not needed>>
+      endif
+
+   where ``<...>'' can be whatever other files or directories
+   you may need.  The SUBDIRS must be properly ordered.
+   *PLEASE NOTE* it is crucial that the SUBDIRS be set under the
+   control of an automake conditional.  To work correctly,
+   automake has to know the range of possible values of SUBDIRS.
+   It's a magical name with magical properties.  ``NEED_LIBOPTS''
+   will be correctly set by the ``LIBOPTS_CHECK'' macro, above.
+
+4. Add ``$(LIBOPTS_CFLAGS)'' to relevant compiler flags and
+   ``$(LIBOPTS_LDADD)'' to relevant link options whereever
+   you need them in your build tree.
+
+5. Make sure your object files explicitly depend upon the
+   generated options header file.  e.g.:
+
+     $(prog_OBJECTS) : prog-opts.h
+     prog-opts.h : prog-opts.c
+     prog-opts.c : prog-opts.def
+         autogen prog-opts.def
+
+6. *OPTIONAL* --
+   If you are creating man pages and texi documentation from
+   the program options, you will need these rules somewhere, too:
+
+     man_MANS = prog.1
+     prog.1 : prog-opts.def
+         autogen -Tagman1.tpl -bprog prog-opts.def
+
+     prog-invoke.texi : prog-opts.def
+         autogen -Taginfo.tpl -bprog-invoke prog-opts.def
+
+If your package does not utilize the auto* tools, then you
+will need to hand craft the rules for building the library.
+
+LICENSING:
+
+This material is copyright 1993-2005 by Bruce Korb.
+You are licensed to use this under the terms of either
+the GNU Lesser General Public License (see: COPYING.lgpl), or,
+at your option, the modified Berkeley Software Distribution
+License (see:  COPYING.mbsd).  Both of these files should be
+included with this tarball.
diff --git a/sntp/libopts/autoopts.c b/sntp/libopts/autoopts.c
new file mode 100644 (file)
index 0000000..2fc5c31
--- /dev/null
@@ -0,0 +1,1033 @@
+
+/*
+ *  $Id: autoopts.c,v 4.9 2005/06/07 22:26:44 bkorb Exp $
+ *  Time-stamp:      "2005-03-13 08:39:23 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef HAVE_PATHFIND
+#  include "compat/pathfind.c"
+#endif
+
+static const char zNil[] = "";
+
+#define SKIP_RC_FILES(po) \
+    DISABLED_OPT(&((po)->pOptDesc[ (po)->specOptIdx.save_opts+1]))
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+doPresets( tOptions* pOpts );
+
+static int
+checkConsistency( tOptions* pOpts );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  handleOption
+ *
+ *  This routine handles equivalencing, sets the option state flags and
+ *  invokes the handler procedure, if any.
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  Save a copy of the option procedure pointer.
+     *  If this is an equivalence class option, we still want this proc.
+     */
+    tOptDesc* pOD = pOptState->pOD;
+    tOptProc* pOP = pOD->pOptProc;
+
+    pOD->pzLastArg =  pOptState->pzOptArg;
+
+    /*
+     *  IF we are presetting options, then we will ignore any un-presettable
+     *  options.  They are the ones either marked as such.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
+       && ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       )
+        return PROBLEM;
+
+    /*
+     *  IF this is an equivalence class option,
+     *  THEN
+     *      Save the option value that got us to this option
+     *      entry.  (It may not be pOD->optChar[0], if this is an
+     *      equivalence entry.)
+     *      set the pointer to the equivalence class base
+     */
+    if (pOD->optEquivIndex != NO_EQUIVALENT) {
+        tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
+
+        /*
+         * IF the current option state has not been defined (set on the
+         *    command line), THEN we will allow continued resetting of
+         *    the value.  Once "defined", then it must not change.
+         */
+        if ((pOD->fOptState & OPTST_DEFINED) != 0) {
+            /*
+             *  The equivalenced-to option has been found on the command
+             *  line before.  Make sure new occurrences are the same type.
+             *
+             *  IF this option has been previously equivalenced and
+             *     it was not the same equivalenced-to option,
+             *  THEN we have a usage problem.
+             */
+            if (p->optActualIndex != pOD->optIndex) {
+                fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
+                         (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
+                return FAILURE;
+            }
+        } else {
+            /*
+             *  Set the equivalenced-to actual option index to no-equivalent
+             *  so that we set all the entries below.  This option may either
+             *  never have been selected before, or else it was selected by
+             *  some sort of "presetting" mechanism.
+             */
+            p->optActualIndex = NO_EQUIVALENT;
+        }
+
+        if (p->optActualIndex != pOD->optIndex) {
+            /*
+             *  First time through, copy over the state
+             *  and add in the equivalence flag
+             */
+            p->optActualValue = pOD->optValue;
+            p->optActualIndex = pOD->optIndex;
+            pOptState->flags |= OPTST_EQUIVALENCE;
+        }
+
+        /*
+         *  Copy the most recent option argument.  set membership state
+         *  is kept in ``p->optCookie''.  Do not overwrite.
+         */
+        p->pzLastArg = pOD->pzLastArg;
+        pOD = p;
+
+    } else {
+        pOD->optActualValue = pOD->optValue;
+        pOD->optActualIndex = pOD->optIndex;
+    }
+
+    pOD->fOptState &= OPTST_PERSISTENT;
+    pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT);
+
+    /*
+     *  Keep track of count only for DEFINED (command line) options.
+     *  IF we have too many, build up an error message and bail.
+     */
+    if (  (pOD->fOptState & OPTST_DEFINED)
+       && (++pOD->optOccCt > pOD->optMaxCt)  )  {
+        const char* pzEqv =
+            (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
+
+        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+            const char* pzFmt = (pOD->optMaxCt > 1) ? zAtMost : zOnlyOne;
+            fputs( zErrOnly, stderr );
+            fprintf( stderr, pzFmt, pOD->pz_Name, pzEqv,
+                     pOD->optMaxCt );
+        }
+
+        return FAILURE;
+    }
+
+    /*
+     *  If provided a procedure to call, call it
+     */
+    if (pOP != (tpOptProc)NULL)
+        (*pOP)( pOpts, pOD );
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  HUNT FOR OPTIONS IN THE ARGUMENT LIST
+ *
+ *  The next four procedures are "private" to nextOption().
+ *  nextOption() uses findOptDesc() to find the next descriptor and it, in
+ *  turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
+ *
+ *  longOptionFind
+ *
+ *  Find the long option descriptor for the current option
+ */
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
+{
+    ag_bool    disable  = AG_FALSE;
+    char*      pzEq     = strchr( pzOptName, '=' );
+    tOptDesc*  pOD      = pOpts->pOptDesc;
+    int        idx      = 0;
+    int        idxLim   = pOpts->optCt;
+    int        matchCt  = 0;
+    int        matchIdx = 0;
+    int        nameLen;
+
+    /*
+     *  IF the value is attached to the name,
+     *  THEN clip it off.
+     *  Either way, figure out how long our name is
+     */
+    if (pzEq != NULL) {
+        nameLen = (int)(pzEq - pzOptName);
+        *pzEq = NUL;
+    } else nameLen = strlen( pzOptName );
+
+    do  {
+        if (SKIP_OPT(pOD))
+            continue;
+
+        if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_Name[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        /*
+         *  IF       there is a disable name
+         *     *AND* no argument value has been supplied
+         *              (disabled options may have no argument)
+         *     *AND* the option name matches the disable name
+         *  THEN ...
+         */
+        else if (  (pOD->pz_DisableName != NULL)
+                && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
+                )  {
+            disable  = AG_TRUE;
+
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_DisableName[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        else
+            continue;
+
+        /*
+         *  We found a partial match, either regular or disabling.
+         *  Remember the index for later.
+         */
+        matchIdx = idx;
+
+        if (++matchCt > 1)
+            break;
+
+    } while (pOD++, (++idx < idxLim));
+
+    if (pzEq != NULL)
+        *(pzEq++) = '=';
+
+    /*
+     *  Make sure we either found an exact match or found only one partial
+     */
+    if (matchCt == 1) {
+        /*
+         *  IF we found a disablement name,
+         *  THEN set the bit in the callers' flag word
+         */
+        if (disable)
+            pOptState->flags |= OPTST_DISABLED;
+
+        pOptState->pOD      = pOpts->pOptDesc + matchIdx;
+        pOptState->pzOptArg = pzEq;
+        pOptState->optType  = TOPT_LONG;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF there is no equal sign
+     *     *AND* we are using named arguments
+     *     *AND* there is a default named option,
+     *  THEN return that option.
+     */
+    if (  (pzEq == NULL)
+       && NAMED_OPTS(pOpts)
+       && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
+        pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
+
+        pOptState->pzOptArg = pzOptName;
+        pOptState->optType  = TOPT_DEFAULT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                 (matchCt == 0) ? zIllegal : zAmbiguous, pzOptName );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  shortOptionFind
+ *
+ *  Find the short option descriptor for the current option
+ */
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tUC optValue, tOptState* pOptState )
+{
+    tOptDesc*  pRes = pOpts->pOptDesc;
+    int        ct   = pOpts->optCt;
+
+    /*
+     *  Search the option list
+     */
+    for (;;) {
+        /*
+         *  IF the values match,
+         *  THEN we stop here
+         */
+        if ((! SKIP_OPT(pRes)) && (optValue == pRes->optValue)) {
+            pOptState->pOD     = pRes;
+            pOptState->optType = TOPT_SHORT;
+            return SUCCESS;
+        }
+
+        /*
+         *  Advance to next option description
+         */
+        pRes++;
+
+        /*
+         *  IF we have searched everything, ...
+         */
+        if (--ct <= 0)
+            break;
+    }
+
+    /*
+     *  IF    the character value is a digit
+     *    AND there is a special number option ("-n")
+     *  THEN the result is the "option" itself and the
+     *       option is the specially marked "number" option.
+     */
+    if (  isdigit( optValue )
+       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
+        pOptState->pOD = \
+        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
+        (pOpts->pzCurOpt)--;
+        pOptState->optType = TOPT_SHORT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  findOptDesc
+ *
+ *  Find the option descriptor for the current option
+ */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  IF we are continuing a short option list (e.g. -xyz...)
+     *  THEN continue a single flag option.
+     *  OTHERWISE see if there is room to advance and then do so.
+     */
+    if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM; /* NORMAL COMPLETION */
+
+    pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+    /*
+     *  IF all arguments must be named options, ...
+     */
+    if (NAMED_OPTS(pOpts)) {
+        char* pz = pOpts->pzCurOpt;
+        pOpts->curOptIdx++;
+
+        /*
+         *  Skip over any flag/option markers.
+         *  In this mode, they are not required.
+         */
+        while (*pz == '-') pz++;
+
+        return longOptionFind( pOpts, pz, pOptState );
+    }
+
+    /*
+     *  Note the kind of flag/option marker
+     */
+    if (*((pOpts->pzCurOpt)++) != '-')
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  Special hack for a hyphen by itself
+     */
+    if (*(pOpts->pzCurOpt) == NUL)
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  The current argument is to be processed as an option argument
+     */
+    pOpts->curOptIdx++;
+
+    /*
+     *  We have an option marker.
+     *  Test the next character for long option indication
+     */
+    if (pOpts->pzCurOpt[0] == '-') {
+        if (*++(pOpts->pzCurOpt) == NUL)
+            /*
+             *  NORMAL COMPLETION - NOT this arg, but rest are operands
+             */
+            return PROBLEM;
+
+        /*
+         *  We do not allow the hyphen to be used as a flag value.
+         *  Therefore, if long options are not to be accepted, we punt.
+         */
+        if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
+            fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                     zIllegal, pOpts->pzCurOpt-2 );
+            return FAILURE;
+        }
+
+        return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+    }
+
+    /*
+     *  If short options are not allowed, then do long
+     *  option processing.  Otherwise the character must be a
+     *  short (i.e. single character) option.
+     */
+    if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+}
+
+
+/*
+ *  nextOption
+ *
+ *  Find the option descriptor and option argument (if any) for the
+ *  next command line argument.  DO NOT modify the descriptor.  Put
+ *  all the state in the state argument so that the option can be skipped
+ *  without consequence (side effect).
+ */
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState )
+{
+    tSuccess res;
+    enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
+
+    res = findOptDesc( pOpts, pOptState );
+    if (! SUCCESSFUL( res ))
+        return res;
+    pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT);
+
+    /*
+     *  Figure out what to do about option arguments.  An argument may be
+     *  required, not associated with the option, or be optional.  We detect the
+     *  latter by examining for an option marker on the next possible argument.
+     *  Disabled mode option selection also disables option arguments.
+     */
+    if ((pOptState->flags & OPTST_DISABLED) != 0)
+        arg_type = ARG_NONE;
+    else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE)
+        arg_type = ARG_NONE;
+    else if (pOptState->flags & OPTST_ARG_OPTIONAL)
+        arg_type = ARG_MAY;
+    else
+        arg_type = ARG_MUST;
+
+    switch (arg_type) {
+    case ARG_MUST:
+        /*
+         *  An option argument is required.  Long options can either have
+         *  a separate command line argument, or an argument attached by
+         *  the '=' character.  Figure out which.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            /*
+             *  See if an arg string follows the flag character
+             */
+            if (*++(pOpts->pzCurOpt) == NUL)
+                pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            pOptState->pzOptArg = pOpts->pzCurOpt;
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  See if an arg string has already been assigned (glued on
+             *  with an `=' character)
+             */
+            if (pOptState->pzOptArg == NULL)
+                pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            break;
+
+        default:
+#ifdef DEBUG
+            fputs( "AutoOpts lib error: option type not selected\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+#endif
+
+        case TOPT_DEFAULT:
+            /*
+             *  The option was selected by default.  The current token is
+             *  the option argument.
+             */
+            break;
+        }
+
+        /*
+         *  Make sure we did not overflow the argument list.
+         */
+        if (pOpts->curOptIdx > pOpts->origArgCt) {
+            fprintf( stderr, zMisArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        pOpts->pzCurOpt = NULL;  /* next time advance to next arg */
+        break;
+
+    case ARG_MAY:
+        /*
+         *  An option argument is optional.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            if (*++pOpts->pzCurOpt != NUL)
+                pOptState->pzOptArg = pOpts->pzCurOpt;
+            else {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  Look for an argument if we don't already have one (glued on
+             *  with a `=' character) *AND* we are not in named argument mode
+             */
+            if (  (pOptState->pzOptArg == NULL)
+               && (! NAMED_OPTS(pOpts))) {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        default:
+        case TOPT_DEFAULT:
+            fputs( "AutoOpts lib error: defaulted to option with optional arg\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+        }
+
+        /*
+         *  After an option with an optional argument, we will
+         *  *always* start with the next option because if there
+         *  were any characters following the option name/flag,
+         *  they would be interpreted as the argument.
+         */
+        pOpts->pzCurOpt = NULL;
+        break;
+
+    default: /* CANNOT */
+        /*
+         *  No option argument.  Make sure next time around we find
+         *  the correct option flag character for short options
+         */
+        if (pOptState->optType == TOPT_SHORT)
+            (pOpts->pzCurOpt)++;
+
+        /*
+         *  It is a long option.  Make sure there was no ``=xxx'' argument
+         */
+        else if (pOptState->pzOptArg != NULL) {
+            fprintf( stderr, zNoArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        /*
+         *  It is a long option.  Advance to next command line argument.
+         */
+        else
+            pOpts->pzCurOpt = NULL;
+    }
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  DO PRESETS
+ *
+ *  The next several routines do the immediate action pass on the command
+ *  line options, then the environment variables, then the config files in
+ *  reverse order.  Once done with that, the order is reversed and all
+ *  the config files and environment variables are processed again, this
+ *  time only processing the non-immediate action options.  doPresets()
+ *  will then return for optionProcess() to do the final pass on the command
+ *  line arguments.
+ */
+
+/*
+ *  doImmediateOpts - scan the command line for immediate action options
+ */
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts )
+{
+    pOpts->curOptIdx = 1;     /* start by skipping program name */
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Examine all the options from the start.  We process any options that
+     *  are marked for immediate processing.
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(PRESET);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this *is* an immediate-attribute option, then do it.
+         */
+        if (! DO_IMMEDIATELY(optState.flags))
+            continue;
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts )
+{
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this is not being processed normally (i.e. is immediate action)
+         *  THEN skip it (unless we are supposed to do it a second time).
+         */
+        if (! DO_NORMALLY(optState.flags)) {
+            if (! DO_SECOND_TIME(optState.flags))
+                continue;
+            optState.pOD->optOccCt--; /* don't count last time */
+        }
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+/*
+ *  doPresets - check for preset values from a config file or the envrionment
+ */
+static tSuccess
+doPresets( tOptions* pOpts )
+{
+    if (! SUCCESSFUL( doImmediateOpts( pOpts )))
+        return FAILURE;
+
+    /*
+     *  Until we return from this procedure, disable non-presettable opts
+     */
+    pOpts->fOptSet |= OPTPROC_PRESETTING;
+    /*
+     *  IF there are no config files,
+     *  THEN do any environment presets and leave.
+     */
+    if (  (pOpts->papzHomeList == NULL)
+       || SKIP_RC_FILES(pOpts) )  {
+        doEnvPresets( pOpts, ENV_ALL );
+    }
+    else {
+        doEnvPresets( pOpts, ENV_IMM );
+        internalFileLoad( pOpts );
+        doEnvPresets( pOpts, ENV_NON_IMM );
+    }
+    pOpts->fOptSet &= ~OPTPROC_PRESETTING;
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  VERIFY OPTION CONSISTENCY
+ *
+ *  Make sure that the argument list passes our consistency tests.
+ */
+static int
+checkConsistency( tOptions* pOpts )
+{
+    int        errCt = 0;
+    tOptDesc*  pOD   = pOpts->pOptDesc;
+    int        oCt   = pOpts->presetOptCt;
+
+    /*
+     *  FOR each of "oCt" options, ...
+     */
+    for (;;) {
+        const int*  pMust = pOD->pOptMust;
+        const int*  pCant = pOD->pOptCant;
+
+        /*
+         *  IF the current option was provided on the command line
+         *  THEN ensure that any "MUST" requirements are not
+         *       "DEFAULT" (unspecified) *AND* ensure that any
+         *       "CANT" options have not been SET or DEFINED.
+         */
+        if (SELECTED_OPT(pOD)) {
+            if (pMust != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pMust++);
+                if (UNUSED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
+                    errCt++;
+                    fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pMust == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pCant != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pCant++);
+                if (SELECTED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
+                    errCt++;
+                    fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pCant == NO_EQUIVALENT)
+                    break;
+            }
+        }
+
+        /*
+         *  IF       this option is not equivalenced to another,
+         *        OR it is equivalenced to itself (is the equiv. root)
+         *  THEN we need to make sure it occurs often enough.
+         */
+        if (  (pOD->optEquivIndex == NO_EQUIVALENT)
+           || (pOD->optEquivIndex == pOD->optIndex) )   do {
+            /*
+             *  IF the occurrence counts have been satisfied,
+             *  THEN there is no problem.
+             */
+            if (pOD->optOccCt >= pOD->optMinCt)
+                break;
+
+            /*
+             *  IF MUST_SET means SET and PRESET are okay,
+             *  so min occurrence count doesn't count
+             */
+            if (  (pOD->fOptState & OPTST_MUST_SET)
+               && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
+                break;
+
+            errCt++;
+            if (pOD->optMinCt > 1)
+                fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
+            else fprintf( stderr, zNeedOne, pOD->pz_Name );
+           } while (0);
+
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF we are stopping on errors, check to see if any remaining
+     *  arguments are required to be there or prohibited from being there.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+
+        /*
+         *  Check for prohibition
+         */
+        if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
+            if (pOpts->origArgCt > pOpts->curOptIdx) {
+                fprintf( stderr, zNoArgs, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+
+        /*
+         *  ELSE not prohibited, check for being required
+         */
+        else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
+            if (pOpts->origArgCt <= pOpts->curOptIdx) {
+                fprintf( stderr, zArgsMust, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+    }
+
+    return errCt;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
+ */
+/*=--subblock=arg=arg_type,arg_name,arg_desc =*/
+/*=*
+ * library:  opts
+ * header:   your-opts.h
+ *
+ * lib_description:
+ *
+ *  These are the routines that libopts users may call directly from their
+ *  code.  There are several other routines that can be called by code
+ *  generated by the libopts option templates, but they are not to be
+ *  called from any other user code.  The @file{options.h} header is
+ *  fairly clear about this, too.
+=*/
+
+/*=export_func optionProcess
+ *
+ * what: this is the main option processing routine
+ *
+ * arg:  + tOptions* + pOpts + program options descriptor +
+ * arg:  + int       + argc  + program arg count  +
+ * arg:  + char**    + argv  + program arg vector +
+ *
+ * ret_type:  int
+ * ret_desc:  the count of the arguments processed
+ *
+ * doc:
+ *
+ * This is the main entry point for processing options.  It is intended
+ * that this procedure be called once at the beginning of the execution of
+ * a program.  Depending on options selected earlier, it is sometimes
+ * necessary to stop and restart option processing, or to select completely
+ * different sets of options.  This can be done easily, but you generally
+ * do not want to do this.
+ *
+ * The number of arguments processed always includes the program name.
+ * If one of the arguments is "--", then it is counted and the processing
+ * stops.  If an error was encountered and errors are to be tolerated, then
+ * the returned value is the index of the argument causing the error.
+ * A hyphen by itself ("-") will also cause processing to stop and will
+ * @emph{not} be counted among the processed arguments.  A hyphen by itself
+ * is treated as an operand.  Encountering an operand stops option
+ * processing.
+ *
+ * err:  Errors will cause diagnostics to be printed.  @code{exit(3)} may
+ *       or may not be called.  It depends upon whether or not the options
+ *       were generated with the "allow-errors" attribute, or if the
+ *       ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
+=*/
+int
+optionProcess(
+    tOptions*  pOpts,
+    int        argCt,
+    char**     argVect )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
+        exit( EXIT_FAILURE );
+
+    /*
+     *  Establish the real program name, the program full path,
+     *  and do all the presetting the first time thru only.
+     */
+    if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
+        pOpts->origArgCt   = argCt;
+        pOpts->origArgVect = argVect;
+        pOpts->fOptSet    |= OPTPROC_INITDONE;
+
+        if (! SUCCESSFUL( doPresets( pOpts )))
+            return 0;
+
+        if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+            optionSort( pOpts );
+
+        pOpts->curOptIdx   = 1;
+        pOpts->pzCurOpt    = NULL;
+    }
+
+    /*
+     *  IF we are (re)starting,
+     *  THEN reset option location
+     */
+    else if (pOpts->curOptIdx <= 0) {
+        pOpts->curOptIdx = 1;
+        pOpts->pzCurOpt  = NULL;
+    }
+
+    if (! SUCCESSFUL( doRegularOpts( pOpts )))
+        return pOpts->origArgCt;
+
+    /*
+     *  IF    there were no errors
+     *    AND we have RC/INI files
+     *    AND there is a request to save the files
+     *  THEN do that now before testing for conflicts.
+     *       (conflicts are ignored in preset options)
+     */
+    if (pOpts->specOptIdx.save_opts != 0) {
+        tOptDesc*  pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
+
+        if (SELECTED_OPT( pOD )) {
+            optionSaveFile( pOpts );
+            exit( EXIT_SUCCESS );
+        }
+    }
+
+    /*
+     *  IF we are checking for errors,
+     *  THEN look for too few occurrences of required options
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        if (checkConsistency( pOpts ) != 0)
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return pOpts->curOptIdx;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.c */
diff --git a/sntp/libopts/autoopts.h b/sntp/libopts/autoopts.h
new file mode 100644 (file)
index 0000000..0b4c0e1
--- /dev/null
@@ -0,0 +1,350 @@
+
+/*
+ *  Time-stamp:      "2005-07-27 10:11:09 bkorb"
+ *
+ *  autoopts.h  $Id: autoopts.h,v 4.12 2005/07/27 17:26:32 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 05:59:50 bkorb"
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef AUTOGEN_AUTOOPTS_H
+#define AUTOGEN_AUTOOPTS_H
+
+#ifndef   __EXTENSIONS__
+#  define __EXTENSIONS__
+#endif
+
+#include "config.h"
+#include "compat/compat.h"
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <utime.h>
+
+#define AO_NAME_LIMIT    127
+#define AO_NAME_SIZE     (AO_NAME_LIMIT + 1)
+
+#ifndef MAXPATHLEN
+#  ifdef PATH_MAX
+#    define MAXPATHLEN   PATH_MAX
+#  else
+#    define MAXPATHLEN   4096
+#  endif
+#else
+#  if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN)
+#     undef  MAXPATHLEN
+#     define MAXPATHLEN  PATH_MAX
+#  endif
+#endif
+
+#undef  EXPORT
+#define EXPORT
+
+/*
+ *  Convert the number to a list usable in a printf call
+ */
+#define NUM_TO_VER(n)       ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F
+
+#define NAMED_OPTS(po) \
+        (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0)
+
+#define SKIP_OPT(p)  (((p)->fOptState & (OPTST_DOCUMENT|OPTST_OMITTED)) != 0)
+
+typedef int tDirection;
+#define DIRECTION_PRESET  -1
+#define DIRECTION_PROCESS  1
+#define DIRECTION_CALLED   0
+
+#define PROCESSING(d)     ((d)>0)
+#define PRESETTING(d)     ((d)<0)
+
+#define ISNAMECHAR( c )    (isalnum(c) || ((c) == '_') || ((c) == '-'))
+
+/*
+ *  Procedure success codes
+ *
+ *  USAGE:  define procedures to return "tSuccess".  Test their results
+ *          with the SUCCEEDED, FAILED and HADGLITCH macros.
+ */
+#define SUCCESS  ((tSuccess) 0)
+#define FAILURE  ((tSuccess)-1)
+#define PROBLEM  ((tSuccess) 1)
+
+typedef int tSuccess;
+
+#define SUCCEEDED( p )     ((p) == SUCCESS)
+#define SUCCESSFUL( p )    SUCCEEDED( p )
+#define FAILED( p )        ((p) <  SUCCESS)
+#define HADGLITCH( p )     ((p) >  SUCCESS)
+
+/*
+ *  The pager state is used by optionPagedUsage() procedure.
+ *  When it runs, it sets itself up to be called again on exit.
+ *  If, however, a routine needs a child process to do some work
+ *  before it is done, then 'pagerState' must be set to
+ *  'PAGER_STATE_CHILD' so that optionPagedUsage() will not try
+ *  to run the pager program before its time.
+ */
+typedef enum {
+    PAGER_STATE_INITIAL,
+    PAGER_STATE_READY,
+    PAGER_STATE_CHILD
+} tePagerState;
+
+extern tePagerState pagerState;
+
+typedef enum {
+    ENV_ALL,
+    ENV_IMM,
+    ENV_NON_IMM
+} teEnvPresetType;
+
+typedef enum {
+    TOPT_UNDEFINED = 0,
+    TOPT_SHORT,
+    TOPT_LONG,
+    TOPT_DEFAULT
+} teOptType;
+
+typedef struct {
+    tOptDesc*  pOD;
+    tCC*       pzOptArg;
+    tUL        flags;
+    teOptType  optType;
+} tOptState;
+#define OPTSTATE_INITIALIZER(st) \
+    { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED }
+
+#define TEXTTO_TABLE \
+        _TT_( LONGUSAGE ) \
+        _TT_( USAGE ) \
+        _TT_( VERSION )
+#define _TT_(n) \
+        TT_ ## n ,
+
+typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo;
+
+#undef _TT_
+
+typedef struct {
+    tCC*    pzStr;
+    tCC*    pzReq;
+    tCC*    pzNum;
+    tCC*    pzKey;
+    tCC*    pzKeyL;
+    tCC*    pzBool;
+    tCC*    pzNest;
+    tCC*    pzOpt;
+    tCC*    pzNo;
+    tCC*    pzBrk;
+    tCC*    pzNoF;
+    tCC*    pzSpc;
+    tCC*    pzOptFmt;
+} arg_types_t;
+
+#  define AGALOC( c, w )        malloc( c )
+#  define AGREALOC( p, c, w )   realloc( p, c )
+#  define AGFREE( p )           free( p )
+#  define AGDUPSTR( p, s, w )   p = strdup( s )
+#  define TAGMEM( m, t )
+
+#ifdef AUTOGEN_BUILD
+#  include <snprintfv/printf.h>
+#endif /* AUTOGEN_BUILD */
+
+/*
+ *  DO option handling?
+ *
+ *  Options are examined at two times:  at immediate handling time and at
+ *  normal handling time.  If an option is disabled, the timing may be
+ *  different from the handling of the undisabled option.  The OPTST_DIABLED
+ *  bit indicates the state of the currently discovered option.
+ *  So, here's how it works:
+ *
+ *  A) handling at "immediate" time, either 1 or 2:
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  1 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   must be set
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x 1 x x
+ */
+#define DO_IMMEDIATELY(_flg) \
+    (  (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \
+    || (   ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    \
+        == (OPTST_DISABLED|OPTST_DISABLE_IMM)  ))
+
+/*  B) handling at "regular" time because it was not immediate
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must *NOT* be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  0 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x x 1 x
+ */
+#define DO_NORMALLY(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_IMM))            == 0)  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    ==     \
+                  OPTST_DISABLED)  )
+
+/*  C)  handling at "regular" time because it is to be handled twice.
+ *      The immediate bit was already tested and found to be set:
+ *
+ *  3.  OPTST_DISABLED is not set:
+ *      IMM           is set (but don't care)
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      0 -and-  ? x 1 x
+ *
+ *  4.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   is set (but don't care)
+ *      TWICE         don't care
+ *      DISABLE_TWICE must be set
+ *      1 -and-  x ? x 1
+ */
+#define DO_SECOND_TIME(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_TWICE))          ==     \
+                  OPTST_TWICE)                                  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE))  ==     \
+                  (OPTST_DISABLED|OPTST_DISABLE_TWICE)  ))
+
+/*
+ *  text_mmap structure.  Only active on platforms with mmap(2).
+ */
+#ifdef HAVE_SYS_MMAN_H
+#  include <sys/mman.h>
+#else
+#  ifndef  PROT_READ
+#   define PROT_READ    0x01
+#  endif
+#  ifndef  PROT_WRITE
+#   define PROT_WRITE   0x02
+#  endif
+#  ifndef  MAP_SHARED
+#   define MAP_SHARED   0x01
+#  endif
+#  ifndef  MAP_PRIVATE
+#   define MAP_PRIVATE  0x02
+#  endif
+#endif
+
+#ifndef MAP_FAILED
+#  define  MAP_FAILED   ((void*)-1)
+#endif
+
+#ifndef  _SC_PAGESIZE
+# ifdef  _SC_PAGE_SIZE
+#  define _SC_PAGESIZE _SC_PAGE_SIZE
+# endif
+#endif
+
+/*
+ *  This is an output only structure used by text_mmap and text_munmap.
+ *  Clients must not alter the contents and must provide it to both
+ *  the text_mmap and text_munmap procedures.  BE ADVISED: if you are
+ *  mapping the file with PROT_WRITE the NUL byte at the end MIGHT NOT
+ *  BE WRITABLE.  In any event, that byte is not be written back
+ *  to the source file.  ALSO: if "txt_data" is valid and "txt_errno"
+ *  is not zero, then there *may* not be a terminating NUL.
+ */
+typedef struct {
+    void*       txt_data;      /* text file data   */
+    size_t      txt_size;      /* actual file size */
+    int         txt_fd;        /* file descriptor  */
+    size_t      txt_full_size; /* mmaped mem size  */
+    int         txt_zero_fd;   /* fd for /dev/zero */
+    int         txt_errno;     /* warning code     */
+    int         txt_prot;      /* "prot" flags     */
+    int         txt_flags;     /* mapping type     */
+} tmap_info_t;
+
+/*
+ *  Define and initialize all the user visible strings.
+ *  We do not do translations.  If translations are to be done, then
+ *  the client will provide a callback for that purpose.
+ */
+#undef DO_TRANSLATIONS
+#include "autoopts/usage-txt.h"
+
+/*
+ *  File pointer for usage output
+ */
+extern FILE* option_usage_fp;
+
+extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt;
+
+#define LOCAL static
+#include "proto.h"
+
+#endif /* AUTOGEN_AUTOOPTS_H */
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.h */
diff --git a/sntp/libopts/autoopts/options.h b/sntp/libopts/autoopts/options.h
new file mode 100644 (file)
index 0000000..677d4b8
--- /dev/null
@@ -0,0 +1,864 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (options.h)
+ *  
+ *  It has been AutoGen-ed  Thursday July 28, 2005 at 04:18:43 PM PDT
+ *  From the definitions    funcs.def
+ *  and the template file   options_h
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ *
+ *  Automated Options copyright 1992-Y Bruce Korb
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts 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
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_OPTIONS_H_GUARD
+#define AUTOOPTS_OPTIONS_H_GUARD
+#include <sys/types.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif /* HAVE_STDINT/INTTYPES_H */
+
+#if defined(HAVE_LIMITS_H)
+# include <limits.h>
+#elif defined(HAVE_SYS_LIMITS_H)
+# include <sys/limits.h>
+#endif /* HAVE_LIMITS/SYS_LIMITS_H */
+
+/*
+ *  PUBLIC DEFINES
+ *
+ *  The following defines may be used in applications that need to test the
+ *  state of an option.  To test against these masks and values, a pointer
+ *  to an option descriptor must be obtained.  There are two ways:
+ *
+ *  1. inside an option processing procedure, it is the second argument,
+ *  conventionally "tOptDesc* pOD".
+ *
+ *  2.  Outside of an option procedure (or to reference a different option
+ *  descriptor), use either "&DESC( opt_name )" or "&pfx_DESC( opt_name )".
+ *
+ *  See the relevant generated header file to determine which and what
+ *  values for "opt_name" are available.
+ */
+
+typedef enum {
+    OPARG_TYPE_NONE             = 0,
+    OPARG_TYPE_STRING           = 1,    /* default type/ vanilla string      */
+    OPARG_TYPE_ENUMERATION      = 2,    /* opt arg is an enum (keyword list) */
+    OPARG_TYPE_BOOLEAN          = 3,    /* opt arg is boolean-valued         */
+    OPARG_TYPE_MEMBERSHIP       = 4,    /* opt arg sets set membership bits  */
+    OPARG_TYPE_NUMERIC          = 5,    /* opt arg has numeric value         */
+    OPARG_TYPE_HIERARCHY        = 6     /* option arg is hierarchical value  */
+} teOptArgType;
+
+typedef struct optionValue {
+    teOptArgType        valType;
+    char*               pzName;
+    union {
+        char            strVal[1];      /* OPARG_TYPE_STRING      */
+        int             enumVal;        /* OPARG_TYPE_ENUMERATION */
+        int             boolVal;        /* OPARG_TYPE_BOOLEAN     */
+        long            setVal;         /* OPARG_TYPE_MEMBERSHIP  */
+        long            longVal;        /* OPARG_TYPE_NUMERIC     */
+        void*           nestVal;        /* OPARG_TYPE_HIERARCHY   */
+    } v;
+} tOptionValue;
+
+#define OPTST_SET_ARGTYPE(n) ((n) << 12)
+#define OPTST_GET_ARGTYPE(f) (((f) & OPTST_ARG_TYPE_MASK) >> 12)
+
+/*
+ *  Bits in the fOptState option descriptor field.
+ */
+#define OPTST_INIT           0x0000000  /* Initial compiled value            */
+#define OPTST_SET            0x0000001  /* Set via the "SET_OPT()" macro     */
+#define OPTST_PRESET         0x0000002  /* Set via an RC/INI file            */
+#define OPTST_DEFINED        0x0000004  /* Set via a command line option     */
+
+#define OPTST_SET_MASK       0x0000007  /* mask of flags that show set state */
+
+#define OPTST_EQUIVALENCE    0x0000010  /* selected by equiv'ed option       */
+#define OPTST_DISABLED       0x0000020  /* option is in disabled state       */
+
+#define OPTST_NO_INIT        0x0000100  /* option cannot be preset           */
+#define OPTST_NUMBER_OPT     0x0000200  /* opt value (flag) is any digit     */
+#define OPTST_STACKED        0x0000400  /* opt uses optionStackArg procedure */
+#define OPTST_INITENABLED    0x0000800  /* option defaults to enabled        */
+#define OPTST_ARG_TYPE_MASK  0x000F000  /* bits used to specify opt arg type */
+#define OPTST_ARG_OPTIONAL   0x0010000  /* the option argument not required  */
+#define OPTST_IMM            0x0020000  /* process option on first pass      */
+#define OPTST_DISABLE_IMM    0x0040000  /* process disablement on first pass */
+#define OPTST_OMITTED        0x0080000  /* compiled out of program           */
+#define OPTST_MUST_SET       0x0100000  /* must be set or pre-set            */
+#define OPTST_DOCUMENT       0x0200000  /* opt is for documentation only     */
+#define OPTST_TWICE          0x0400000  /* process option twice - imm + reg  */
+#define OPTST_DISABLE_TWICE  0x0800000  /* process disabled option twice     */
+
+#define OPTST_PERSISTENT     0xFFFFF00  /* mask of flags that do not change  */
+
+#define SELECTED_OPT( pod )  ( (pod)->fOptState & (OPTST_SET | OPTST_DEFINED))
+#define UNUSED_OPT(   pod )  (((pod)->fOptState & OPTST_SET_MASK) == 0)
+#define DISABLED_OPT( pod )  ( (pod)->fOptState & OPTST_DISABLED)
+#define OPTION_STATE( pod )  ((pod)->fOptState)
+
+/*
+ *  PRIVATE INTERFACES
+ *
+ *  The following values are used in the generated code to communicate
+ *  with the option library procedures.  They are not for public use
+ *  and may be subject to change.
+ */
+
+/*
+ *  Define any special processing flags
+ */
+#define OPTPROC_NONE        0x000000
+#define OPTPROC_LONGOPT     0x000001 /* Process long style options      */
+#define OPTPROC_SHORTOPT    0x000002 /* Process short style "flags"     */
+#define OPTPROC_ERRSTOP     0x000004 /* Stop on argument errors         */
+#define OPTPROC_DISABLEDOPT 0x000008 /* Current option is disabled      */
+#define OPTPROC_NO_REQ_OPT  0x000010 /* no options are required         */
+#define OPTPROC_NUM_OPT     0x000020 /* there is a number option        */
+#define OPTPROC_INITDONE    0x000040 /* have initializations been done? */
+#define OPTPROC_NEGATIONS   0x000080 /* any negation options?           */
+#define OPTPROC_ENVIRON     0x000100 /* check environment?              */
+#define OPTPROC_NO_ARGS     0x000200 /* Disallow remaining arguments    */
+#define OPTPROC_ARGS_REQ    0x000400 /* Require arguments after options */
+#define OPTPROC_REORDER     0x000800 /* reorder arguments after options */
+#define OPTPROC_GNUUSAGE    0x001000 /* emit usage in GNU style         */
+#define OPTPROC_TRANSLATE   0x002000 /* Translate strings in tOptions   */
+#define OPTPROC_HAS_IMMED   0x004000 /* program defines immed options   */
+#define OPTPROC_PRESETTING  0x800000 /* opt processing in preset state  */
+
+#define STMTS(s)  do { s; } while (0)
+
+/*
+ *  The following must be #defined instead of typedef-ed
+ *  because "static const" cannot both be applied to a type,
+ *  tho each individually can...so they all are
+ */
+#define tSCC      static const char
+#define tSC       static char
+#define tCUC      const unsigned char
+#define tUC       unsigned char
+#define tCC       const char
+#define tUI       unsigned int
+#define tUL       unsigned long
+
+/*
+ *  It is so disgusting that there must be so many ways
+ *  of specifying TRUE and FALSE.
+ */
+typedef enum { AG_FALSE = 0, AG_TRUE } ag_bool;
+
+/*
+ *  Define a structure that describes each option and
+ *  a pointer to the procedure that handles it.
+ *  The argument is the count of this flag previously seen.
+ */
+typedef struct options  tOptions;
+typedef struct optDesc  tOptDesc;
+typedef struct optNames tOptNames;
+
+/*
+ *  The option procedures do the special processing for each
+ *  option flag that needs it.
+ */
+typedef void (tOptProc)( tOptions*  pOpts, tOptDesc* pOptDesc );
+typedef tOptProc*  tpOptProc;
+
+/*
+ *  The usage procedure will never return.  It calls "exit(2)"
+ *  with the "exitCode" argument passed to it.
+ */
+typedef void (tUsageProc)( tOptions* pOpts, int exitCode );
+typedef tUsageProc* tpUsageProc;
+
+/*
+ *  Special definitions.  "NOLIMIT" is the 'max' value to use when
+ *  a flag may appear multiple times without limit.  "NO_EQUIVALENT"
+ *  is an illegal value for 'optIndex' (option description index).
+ */
+#define NOLIMIT          USHRT_MAX
+#define OPTION_LIMIT     SHRT_MAX
+#define NO_EQUIVALENT    (OPTION_LIMIT+1)
+
+/*
+ *  Special values for optValue.  It must not be generatable from the
+ *  computation "optIndex +96".  Since "optIndex" is limited to 100, ...
+ */
+#define NUMBER_OPTION    '#'
+
+typedef struct argList tArgList;
+#define MIN_ARG_ALLOC_CT   6
+#define INCR_ARG_ALLOC_CT  8
+struct argList {
+    int               useCt;
+    int               allocCt;
+    tCC*              apzArgs[ MIN_ARG_ALLOC_CT ];
+};
+
+/*
+ *  Descriptor structure for each option.
+ *  Only the fields marked "PUBLIC" are for public use.
+ */
+struct optDesc {
+    uint16_t          optIndex;         /* PUBLIC */
+    uint16_t          optValue;         /* PUBLIC */
+    uint16_t          optActualIndex;   /* PUBLIC */
+    uint16_t          optActualValue;   /* PUBLIC */
+
+    uint16_t          optEquivIndex;    /* PUBLIC */
+    uint16_t          optMinCt;
+    uint16_t          optMaxCt;
+    uint16_t          optOccCt;         /* PUBLIC */
+
+    uint32_t          fOptState;        /* PUBLIC */
+    uint32_t          reserved;
+    tCC*              pzLastArg;        /* PUBLIC */
+    void*             optCookie;        /* PUBLIC */
+
+    const int *       pOptMust;
+    const int *       pOptCant;
+    tpOptProc         pOptProc;
+    const char*       pzText;
+
+    const char*       pz_NAME;
+    const char*       pz_Name;
+    const char*       pz_DisableName;
+    const char*       pz_DisablePfx;
+};
+
+/*
+ *  Some options need special processing, so we store their
+ *  indexes in a known place:
+ */
+typedef struct optSpecIndex tOptSpecIndex;
+struct optSpecIndex {
+    uint16_t          more_help;
+    uint16_t          save_opts;
+    uint16_t          number_option;
+    uint16_t          default_opt;
+};
+
+#define  OPTIONS_STRUCT_VERSION  102400
+#define  OPTIONS_VERSION_STRING  "25:2:0"
+#define  OPTIONS_MINIMUM_VERSION 102400
+#define  OPTIONS_MIN_VER_STRING  "25:0:0"
+
+/*
+ *  The procedure generated for translating option text
+ */
+typedef void (tOptionXlateProc)(void);
+
+struct options {
+    const int         structVersion;
+    int               origArgCt;
+    char**            origArgVect;
+    tUI               fOptSet;
+    tUI               curOptIdx;
+    char*             pzCurOpt;
+
+    const char*       pzProgPath;
+    const char*       pzProgName;
+    const char*       pzPROGNAME;
+    const char*       pzRcName;
+    const char*       pzCopyright;
+    const char*       pzCopyNotice;
+    const char*       pzFullVersion;
+    const char**      papzHomeList;
+    const char*       pzUsageTitle;
+    const char*       pzExplain;
+    const char*       pzDetail;
+    tOptDesc*         pOptDesc;
+    const char*       pzBugAddr;
+
+    void*             pExtensions;
+    void*             pSavedState;
+
+    tpUsageProc       pUsageProc;
+    tOptionXlateProc* pTransProc;
+
+    tOptSpecIndex     specOptIdx;
+    const int         optCt;
+    const int         presetOptCt;
+};
+
+/*
+ *  "token list" structure returned by "string_tokenize()"
+ */
+typedef struct {
+    unsigned long   tkn_ct;
+    unsigned char*  tkn_list[1];
+} token_list_t;
+
+/*
+ *  Hide the interface - it pollutes a POSIX claim, but leave it for
+ *  anyone #include-ing this header
+ */
+#define strneqvcmp      option_strneqvcmp
+#define streqvcmp       option_streqvcmp
+#define streqvmap       option_streqvmap
+#define strequate       option_strequate
+#define strtransform    option_strtransform
+
+/*
+ *  When loading a line (or block) of text as an option, the value can
+ *  be processed in any of several modes:
+ *
+ *  @table @samp
+ *  @item keep
+ *  Every part of the value between the delimiters is saved.
+ *
+ *  @item uncooked
+ *  Even if the value begins with quote characters, do not do quote processing.
+ *
+ *  @item cooked
+ *  If the value looks like a quoted string, then process it.
+ *  Double quoted strings are processed the way strings are in "C" programs,
+ *  except they are treated as regular characters if the following character
+ *  is not a well-established escape sequence.
+ *  Single quoted strings (quoted with apostrophies) are handled the way
+ *  strings are handled in shell scripts, *except* that backslash escapes
+ *  are honored before backslash escapes and apostrophies.
+ *  @end table
+ */
+typedef enum {
+    OPTION_LOAD_COOKED,
+    OPTION_LOAD_UNCOOKED,
+    OPTION_LOAD_KEEP
+} tOptionLoadMode;
+
+#ifdef  __cplusplus
+extern "C" {
+#define CPLUSPLUS_CLOSER }
+#else
+#define CPLUSPLUS_CLOSER
+#endif
+
+/*
+ *  The following routines may be coded into AutoOpts client code:
+ */
+
+/* From: tokenize.c line 115
+ *
+ * ao_string_tokenize - tokenize an input string
+ *
+ * Arguments:
+ *   string       string to be tokenized
+ *
+ * Returns: token_list_t* - pointer to a structure that lists each token
+ *
+ *  This function will convert one input string into a list of strings.
+ *  The list of strings is derived by separating the input based on
+ *  white space separation.  However, if the input contains either single
+ *  or double quote characters, then the text after that character up to
+ *  a matching quote will become the string in the list.
+ *  
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *  
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *  
+ *  There are two types of quoted strings: single quoted (@code{'}) and
+ *  double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ *  escape characters (@code{\\}) are simply another character, except when
+ *  preceding the following characters:
+ *  @example
+ *  @code{\\}  double backslashes reduce to one
+ *  @code{'}   incorporates the single quote into the string
+ *  @code{\n}  suppresses both the backslash and newline character
+ *  @end example
+ *  
+ *  Double quote strings are formed according to the rules of string
+ *  constants in ANSI-C programs.
+ */
+extern token_list_t* ao_string_tokenize( const char* );
+
+
+/* From: configfile.c line 113
+ *
+ * configFileLoad - parse a configuration file
+ *
+ * Arguments:
+ *   pzFile       the file to load
+ *
+ * Returns: const tOptionValue* - An allocated, compound value structure
+ *
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ */
+extern const tOptionValue* configFileLoad( const char* );
+
+
+/* From: configfile.c line 869
+ *
+ * optionFileLoad - Load the locatable config files, in order
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzProg       program name
+ *
+ * Returns: int - 0 -> SUCCESS, -1 -> FAILURE
+ *
+ *  This function looks in all the specified directories for a configuration
+ *  file ("rc" file or "ini" file) and processes any found twice.  The first
+ *  time through, they are processed in reverse order (last file first).  At
+ *  that time, only "immediate action" configurables are processed.  For
+ *  example, if the last named file specifies not processing any more
+ *  configuration files, then no more configuration files will be processed.
+ *  Such an option in the @strong{first} named directory will have no effect.
+ *  
+ *  Once the immediate action configurables have been handled, then the
+ *  directories are handled in normal, forward order.  In that way, later
+ *  config files can override the settings of earlier config files.
+ *  
+ *  See the AutoOpts documentation for a thorough discussion of the
+ *  config file format.
+ *  
+ *  Configuration files not found or not decipherable are simply ignored.
+ */
+extern int optionFileLoad( tOptions*, const char* );
+
+
+/* From: configfile.c line 241
+ *
+ * optionFindNextValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   pPrevVal     the last entry
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ */
+extern const tOptionValue* optionFindNextValue( const tOptDesc*, const tOptionValue*, const char*, const char* );
+
+
+/* From: configfile.c line 166
+ *
+ * optionFindValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ */
+extern const tOptionValue* optionFindValue( const tOptDesc*, const char*, const char* );
+
+
+/* From: restore.c line 157
+ *
+ * optionFree - free allocated option processing memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  AutoOpts sometimes allocates memory and puts pointers to it in the
+ *  option state structures.  This routine deallocates all such memory.
+ */
+extern void optionFree( tOptions* );
+
+
+/* From: configfile.c line 310
+ *
+ * optionGetValue - get a specific value from a hierarcical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal value
+ *   valueName    name of value to get
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ */
+extern const tOptionValue* optionGetValue( const tOptionValue*, const char* );
+
+
+/* From: load.c line 473
+ *
+ * optionLoadLine - process a string for an option name and value
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzLine       NUL-terminated text
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *  
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ */
+extern void optionLoadLine( tOptions*, const char* );
+
+
+/* From: configfile.c line 369
+ *
+ * optionNextValue - get the next value from a hierarchical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal list value
+ *   pOldValue    a value from this list
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ */
+extern const tOptionValue* optionNextValue( const tOptionValue*, const tOptionValue* );
+
+
+/* From: autoopts.c line 924
+ *
+ * optionProcess - this is the main option processing routine
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   argc         program arg count
+ *   argv         program arg vector
+ *
+ * Returns: int - the count of the arguments processed
+ *
+ *  This is the main entry point for processing options.  It is intended
+ *  that this procedure be called once at the beginning of the execution of
+ *  a program.  Depending on options selected earlier, it is sometimes
+ *  necessary to stop and restart option processing, or to select completely
+ *  different sets of options.  This can be done easily, but you generally
+ *  do not want to do this.
+ *  
+ *  The number of arguments processed always includes the program name.
+ *  If one of the arguments is "--", then it is counted and the processing
+ *  stops.  If an error was encountered and errors are to be tolerated, then
+ *  the returned value is the index of the argument causing the error.
+ *  A hyphen by itself ("-") will also cause processing to stop and will
+ *  @emph{not} be counted among the processed arguments.  A hyphen by itself
+ *  is treated as an operand.  Encountering an operand stops option
+ *  processing.
+ */
+extern int optionProcess( tOptions*, int, char** );
+
+
+/* From: restore.c line 121
+ *
+ * optionRestore - restore option state from memory copy
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  Copy back the option state from saved memory.
+ *  The allocated memory is left intact, so this routine can be
+ *  called repeatedly without having to call optionSaveState again.
+ *  If you are restoring a state that was saved before the first call
+ *  to optionProcess(3AO), then you may change the contents of the
+ *  argc/argv parameters to optionProcess.
+ */
+extern void optionRestore( tOptions* );
+
+
+/* From: save.c line 325
+ *
+ * optionSaveFile - saves the option state to a file
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will save the state of option processing to a file.  The name
+ *  of that file can be specified with the argument to the @code{--save-opts}
+ *  option, or by appending the @code{rcfile} attribute to the last
+ *  @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ *  will default to @code{.@i{programname}rc}.  If you wish to specify another
+ *  file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ */
+extern void optionSaveFile( tOptions* );
+
+
+/* From: restore.c line 54
+ *
+ * optionSaveState - saves the option state to memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will allocate enough memory to save the current
+ *  option processing state.  If this routine has been called before,
+ *  that memory will be reused.  You may only save one copy of the
+ *  option state.  This routine may be called before optionProcess(3AO).
+ *  If you do call it before the first call to optionProcess, then
+ *  you may also change the contents of argc/argv after you call
+ *  optionRestore(3AO)
+ */
+extern void optionSaveState( tOptions* );
+
+
+/* From: nested.c line 527
+ *
+ * optionUnloadNested - Deallocate the memory for a nested value
+ *
+ * Arguments:
+ *   pOptVal      the hierarchical value
+ *
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+ */
+extern void optionUnloadNested( const tOptionValue* );
+
+
+/* From: version.c line 58
+ *
+ * optionVersion - return the compiled AutoOpts version number
+ *
+ * Returns: const char* - the version string in constant memory
+ *
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+ */
+extern const char* optionVersion( void );
+
+
+/* From: ../compat/pathfind.c line 24
+ *
+ * pathfind - fild a file in a list of directories
+ *
+ * Arguments:
+ *   path         colon separated list of search directories
+ *   file         the name of the file to look for
+ *   mode         the mode bits that must be set to match
+ *
+ * Returns: char* - the path to the located file
+ *
+ * the pathfind function is available only if HAVE_PATHFIND is not defined
+ *
+ *  pathfind looks for a a file with name "FILE" and "MODE" access
+ *  along colon delimited "PATH", and returns the full pathname as a
+ *  string, or NULL if not found.  If "FILE" contains a slash, then
+ *  it is treated as a relative or absolute path and "PATH" is ignored.
+ *  
+ *  @strong{NOTE}: this function is compiled into @file{libopts} only if
+ *  it is not natively supplied.
+ *  
+ *  The "MODE" argument is a string of option letters chosen from the
+ *  list below:
+ *  @example
+ *  Letter    Meaning
+ *  r         readable
+ *  w         writable
+ *  x         executable
+ *  f         normal file       (NOT IMPLEMENTED)
+ *  b         block special     (NOT IMPLEMENTED)
+ *  c         character special (NOT IMPLEMENTED)
+ *  d         directory         (NOT IMPLEMENTED)
+ *  p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *  u         set user ID bit   (NOT IMPLEMENTED)
+ *  g         set group ID bit  (NOT IMPLEMENTED)
+ *  k         sticky bit        (NOT IMPLEMENTED)
+ *  s         size nonzero      (NOT IMPLEMENTED)
+ *  @end example
+ */
+#ifndef HAVE_PATHFIND
+extern char* pathfind( const char*, const char*, const char* );
+#endif /* HAVE_PATHFIND */
+
+
+/* From: streqvcmp.c line 233
+ *
+ * strequate - map a list of characters to the same value
+ *
+ * Arguments:
+ *   ch_list      characters to equivalence
+ *
+ *  Each character in the input string get mapped to the first character
+ *  in the string.
+ *  This function name is mapped to option_strequate so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strequate( const char* );
+
+
+/* From: streqvcmp.c line 143
+ *
+ * streqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  This function name is mapped to option_streqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int streqvcmp( const char*, const char* );
+
+
+/* From: streqvcmp.c line 180
+ *
+ * streqvmap - Set the character mappings for the streqv functions
+ *
+ * Arguments:
+ *   From         Input character
+ *   To           Mapped-to character
+ *   ct           compare length
+ *
+ *  Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ *  the map is cleared by setting all entries in the map to their index
+ *  value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ *  character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ *  are incremented and the process repeated until @code{ct} entries have been
+ *  set. For example,
+ *  @example
+ *  streqvmap( 'a', 'A', 26 );
+ *  @end example
+ *  @noindent
+ *  will alter the mapping so that all English lower case letters
+ *  will map to upper case.
+ *  
+ *  This function name is mapped to option_streqvmap so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void streqvmap( char, char, int );
+
+
+/* From: streqvcmp.c line 102
+ *
+ * strneqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *   ct           compare length
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  The comparison is limited to @code{ct} bytes.
+ *  This function name is mapped to option_strneqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int strneqvcmp( tCC*, tCC*, int );
+
+
+/* From: streqvcmp.c line 259
+ *
+ * strtransform - convert a string into its mapped-to value
+ *
+ * Arguments:
+ *   dest         output string
+ *   src          input string
+ *
+ *  Each character in the input string is mapped and the mapped-to
+ *  character is put into the output.
+ *  This function name is mapped to option_strtransform so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strtransform( char*, const char* );
+
+/*  AutoOpts PRIVATE FUNCTIONS:  */
+tOptProc optionStackArg, optionUnstackArg, optionBooleanVal, optionNumericVal;
+
+extern char* ao_string_cook( char*, int* );
+
+extern unsigned int ao_string_cook_escape_char( const char*, char*, char );
+
+extern void genshelloptUsage( tOptions*, int );
+
+extern void optionBooleanVal( tOptions*, tOptDesc* );
+
+extern char* optionEnumerationVal( tOptions*, tOptDesc*, tCC**, unsigned int );
+
+extern tOptionValue* optionLoadNested( const char*, const char*, size_t, tOptionLoadMode );
+
+extern void optionLoadOpt( tOptions*, tOptDesc* );
+
+extern ag_bool optionMakePath( char*, int, tCC*, tCC* );
+
+extern void optionNestedVal( tOptions*, tOptDesc* );
+
+extern void optionNumericVal( tOptions*, tOptDesc* );
+
+extern void optionPagedUsage( tOptions*, tOptDesc* );
+
+extern void optionParseShell( tOptions* );
+
+extern void optionPrintVersion( tOptions*, tOptDesc* );
+
+extern void optionPutShell( tOptions* );
+
+extern void optionSetMembers( tOptions*, tOptDesc*, tCC**, unsigned int );
+
+extern void optionStackArg( tOptions*, tOptDesc* );
+
+extern void optionUnstackArg( tOptions*, tOptDesc* );
+
+extern void optionUsage( tOptions*, int );
+
+extern void optionVersionStderr( tOptions*, tOptDesc* );
+
+CPLUSPLUS_CLOSER
+#endif /* AUTOOPTS_OPTIONS_H_GUARD */
+/*
+ * Local Variables:
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/sntp/libopts/autoopts/usage-txt.h b/sntp/libopts/autoopts/usage-txt.h
new file mode 100644 (file)
index 0000000..f92e381
--- /dev/null
@@ -0,0 +1,479 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (usage-txt.h)
+ *  
+ *  It has been AutoGen-ed  Thursday July 28, 2005 at 04:18:43 PM PDT
+ *  From the definitions    usage-txt.def
+ *  and the template file   usage-txt.tpl
+ *
+ *  This file handles all the bookkeeping required for tracking all the little
+ *  tiny strings used by the AutoOpts library.  There are 114
+ *  of them.  This is not versioned because it is entirely internal to the
+ *  library and accessed by client code only in a very well-controlled way:
+ *  they may substitute translated strings using a procedure that steps through
+ *  all the string pointers.
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts 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
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_USAGE_TXT_H_GUARD
+#define AUTOOPTS_USAGE_TXT_H_GUARD
+
+#undef  cch_t
+#define cch_t const char
+
+/*
+ *  One structure to hold all the pointers to all the stringlets.
+ */
+typedef struct {
+  int       field_ct;
+  char*     utpz_GnuBoolArg;
+  char*     utpz_GnuKeyArg;
+  char*     utpz_GnuKeyLArg;
+  char*     utpz_GnuNumArg;
+  char*     utpz_GnuStrArg;
+  cch_t*    apz_str[ 109 ];
+} usage_text_t;
+
+/*
+ *  Declare the global structure with all the pointers to translated
+ *  strings.  This is then used by the usage generation procedure.
+ */
+extern usage_text_t option_usage_text;
+
+#if defined(AUTOOPTS_INTERNAL) /* DEFINE ALL THE STRINGS = = = = = */
+/*
+ *  Provide a mapping from a short name to fields in this structure.
+ */
+#define zAO_Bad               (option_usage_text.apz_str[0])
+#define zAO_Big               (option_usage_text.apz_str[1])
+#define zAO_Err               (option_usage_text.apz_str[2])
+#define zAO_Sml               (option_usage_text.apz_str[3])
+#define zAll                  (option_usage_text.apz_str[4])
+#define zAlt                  (option_usage_text.apz_str[5])
+#define zAmbigKey             (option_usage_text.apz_str[6])
+#define zAmbiguous            (option_usage_text.apz_str[7])
+#define zArgsMust             (option_usage_text.apz_str[8])
+#define zAtMost               (option_usage_text.apz_str[9])
+#define zAuto                 (option_usage_text.apz_str[10])
+#define zBadPipe              (option_usage_text.apz_str[11])
+#define zBadVerArg            (option_usage_text.apz_str[12])
+#define zCantFmt              (option_usage_text.apz_str[13])
+#define zCantSave             (option_usage_text.apz_str[14])
+#define zDefaultOpt           (option_usage_text.apz_str[15])
+#define zDis                  (option_usage_text.apz_str[16])
+#define zEnab                 (option_usage_text.apz_str[17])
+#define zEquiv                (option_usage_text.apz_str[18])
+#define zErrOnly              (option_usage_text.apz_str[19])
+#define zExamineFmt           (option_usage_text.apz_str[20])
+#define zFiveSpaces           (option_usage_text.apz_str[21])
+#define zFlagOkay             (option_usage_text.apz_str[22])
+#define zFmtFmt               (option_usage_text.apz_str[23])
+#define zForkFail             (option_usage_text.apz_str[24])
+#define zFSErrOptLoad         (option_usage_text.apz_str[25])
+#define zFSErrReadFile        (option_usage_text.apz_str[26])
+#define zGenshell             (option_usage_text.apz_str[27])
+#define zGnuBoolArg           (option_usage_text.utpz_GnuBoolArg)
+#define zGnuBreak             (option_usage_text.apz_str[28])
+#define zGnuKeyArg            (option_usage_text.utpz_GnuKeyArg)
+#define zGnuKeyLArg           (option_usage_text.utpz_GnuKeyLArg)
+#define zGnuNestArg           (option_usage_text.apz_str[29])
+#define zGnuNumArg            (option_usage_text.utpz_GnuNumArg)
+#define zGnuOptArg            (option_usage_text.apz_str[30])
+#define zGnuOptFmt            (option_usage_text.apz_str[31])
+#define zGnuStrArg            (option_usage_text.utpz_GnuStrArg)
+#define zHomePath             (option_usage_text.apz_str[32])
+#define zIllOptChr            (option_usage_text.apz_str[33])
+#define zIllOptStr            (option_usage_text.apz_str[34])
+#define zIllegal              (option_usage_text.apz_str[35])
+#define zInvalOptDesc         (option_usage_text.apz_str[36])
+#define zKeyWords             (option_usage_text.apz_str[37])
+#define zLoadCooked           (option_usage_text.apz_str[38])
+#define zLoadKeep             (option_usage_text.apz_str[39])
+#define zLoadType             (option_usage_text.apz_str[40])
+#define zLoadUncooked         (option_usage_text.apz_str[41])
+#define zLtypeInteger         (option_usage_text.apz_str[42])
+#define zLtypeNest            (option_usage_text.apz_str[43])
+#define zLtypeString          (option_usage_text.apz_str[44])
+#define zLtypeBool            (option_usage_text.apz_str[45])
+#define zLtypeKeyword         (option_usage_text.apz_str[46])
+#define zLtypeSetMembership   (option_usage_text.apz_str[47])
+#define zMembers              (option_usage_text.apz_str[48])
+#define zMisArg               (option_usage_text.apz_str[49])
+#define zMultiEquiv           (option_usage_text.apz_str[50])
+#define zMust                 (option_usage_text.apz_str[51])
+#define zNeedOne              (option_usage_text.apz_str[52])
+#define zNoArg                (option_usage_text.apz_str[53])
+#define zNoArgs               (option_usage_text.apz_str[54])
+#define zNoCreat              (option_usage_text.apz_str[55])
+#define zNoFlags              (option_usage_text.apz_str[56])
+#define zNoKey                (option_usage_text.apz_str[57])
+#define zNoLim                (option_usage_text.apz_str[58])
+#define zNoPreset             (option_usage_text.apz_str[59])
+#define zNoRq_NoShrtTtl       (option_usage_text.apz_str[60])
+#define zNoRq_ShrtTtl         (option_usage_text.apz_str[61])
+#define zNoStat               (option_usage_text.apz_str[62])
+#define zNoState              (option_usage_text.apz_str[63])
+#define zNone                 (option_usage_text.apz_str[64])
+#define zNotDef               (option_usage_text.apz_str[65])
+#define zNotEnough            (option_usage_text.apz_str[66])
+#define zNotFile              (option_usage_text.apz_str[67])
+#define zNotNumber            (option_usage_text.apz_str[68])
+#define zNrmOptFmt            (option_usage_text.apz_str[69])
+#define zNumberOpt            (option_usage_text.apz_str[70])
+#define zOneSpace             (option_usage_text.apz_str[71])
+#define zOnlyOne              (option_usage_text.apz_str[72])
+#define zOptsOnly             (option_usage_text.apz_str[73])
+#define zPathFmt              (option_usage_text.apz_str[74])
+#define zPlsSendBugs          (option_usage_text.apz_str[75])
+#define zPreset               (option_usage_text.apz_str[76])
+#define zPresetFile           (option_usage_text.apz_str[77])
+#define zPresetIntro          (option_usage_text.apz_str[78])
+#define zProg                 (option_usage_text.apz_str[79])
+#define zProhib               (option_usage_text.apz_str[80])
+#define zReorder              (option_usage_text.apz_str[81])
+#define zReqFmt               (option_usage_text.apz_str[82])
+#define zReqOptFmt            (option_usage_text.apz_str[83])
+#define zReqThese             (option_usage_text.apz_str[84])
+#define zReq_NoShrtTtl        (option_usage_text.apz_str[85])
+#define zReq_ShrtTtl          (option_usage_text.apz_str[86])
+#define zSepChars             (option_usage_text.apz_str[87])
+#define zSetMembers           (option_usage_text.apz_str[88])
+#define zSetMemberSettings    (option_usage_text.apz_str[89])
+#define zShrtGnuOptFmt        (option_usage_text.apz_str[90])
+#define zSixSpaces            (option_usage_text.apz_str[91])
+#define zStdBoolArg           (option_usage_text.apz_str[92])
+#define zStdBreak             (option_usage_text.apz_str[93])
+#define zStdKeyArg            (option_usage_text.apz_str[94])
+#define zStdKeyLArg           (option_usage_text.apz_str[95])
+#define zStdNestArg           (option_usage_text.apz_str[96])
+#define zStdNoArg             (option_usage_text.apz_str[97])
+#define zStdNumArg            (option_usage_text.apz_str[98])
+#define zStdOptArg            (option_usage_text.apz_str[99])
+#define zStdReqArg            (option_usage_text.apz_str[100])
+#define zStdStrArg            (option_usage_text.apz_str[101])
+#define zTabHyp               (option_usage_text.apz_str[102])
+#define zTabHypAnd            (option_usage_text.apz_str[103])
+#define zTabout               (option_usage_text.apz_str[104])
+#define zThreeSpaces          (option_usage_text.apz_str[105])
+#define zTwoSpaces            (option_usage_text.apz_str[106])
+#define zUpTo                 (option_usage_text.apz_str[107])
+#define zValidKeys            (option_usage_text.apz_str[108])
+
+  /*
+   *  First, set up the strings.  Some of these are writable.  These are all in
+   *  English.  This gets compiled into libopts and is distributed here so that
+   *  xgettext (or equivalents) can extract these strings for translation.
+   */
+
+  static cch_t   eng_zAO_Bad[] =
+       "AutoOpts function called without option descriptor\n";
+  static cch_t   eng_zAO_Big[] =
+       "\tThis exceeds the compiled library version:  ";
+  static cch_t   eng_zAO_Err[] =
+       "Automated Options Processing Error!\n\
+\t%s called AutoOpts function with structure version %d:%d:%d.\n";
+  static cch_t   eng_zAO_Sml[] =
+       "\tThis is less than the minimum library version:  ";
+  static cch_t   eng_zAll[] =
+       "all";
+  static cch_t   eng_zAlt[] =
+       "\t\t\t\t- an alternate for %s\n";
+  static cch_t   eng_zAmbigKey[] =
+       "%s error:  the keyword `%s' is ambiguous\n";
+  static cch_t   eng_zAmbiguous[] =
+       "ambiguous";
+  static cch_t   eng_zArgsMust[] =
+       "%s: Command line arguments required\n";
+  static cch_t   eng_zAtMost[] =
+       "%4$d %1$s%s options allowed\n";
+  static cch_t   eng_zAuto[] =
+       "version and help options:";
+  static cch_t   eng_zBadPipe[] =
+       "Error %d (%s) from the pipe(2) syscall\n";
+  static cch_t   eng_zBadVerArg[] =
+       "ERROR: version option argument '%c' invalid.  Use:\n\
+\t'v' - version only\n\
+\t'c' - version and copyright\n\
+\t'n' - version and copyright notice\n";
+  static cch_t   eng_zCantFmt[] =
+       "ERROR:  %s option conflicts with the %s option\n";
+  static cch_t   eng_zCantSave[] =
+       "%s(optionSaveState): error: cannot allocate %d bytes\n";
+  static cch_t   eng_zDefaultOpt[] =
+       "\t\t\t\t- default option for unnamed options\n";
+  static cch_t   eng_zDis[] =
+       "\t\t\t\t- disabled as --%s\n";
+  static cch_t   eng_zEnab[] =
+       "\t\t\t\t- enabled by default\n";
+  static cch_t   eng_zEquiv[] =
+       "-equivalence";
+  static cch_t   eng_zErrOnly[] =
+       "ERROR:  only ";
+  static cch_t   eng_zExamineFmt[] =
+       " - examining environment variables named %s_*\n";
+  static cch_t   eng_zFiveSpaces[] =
+       "     ";
+  static cch_t   eng_zFlagOkay[] =
+       "Options are specified by doubled hyphens and their name\n\
+or by a single hyphen and the flag character.\n";
+  static cch_t   eng_zFmtFmt[] =
+       "%%-%ds %%s\n";
+  static cch_t   eng_zForkFail[] =
+       "fs error %d (%s) on fork - cannot obtain %s usage\n";
+  static cch_t   eng_zFSErrOptLoad[] =
+       "File error %d (%s) opening %s for loading options\n";
+  static cch_t   eng_zFSErrReadFile[] =
+       "fs error %d (%s) reading file %s\n";
+  static cch_t   eng_zGenshell[] =
+       "\n\
+= = = = = = = =\n\n\
+This incarnation of genshell will produce\n\
+a shell script to parse the options for %s:\n\n";
+  static char    eng_zGnuBoolArg[] =
+       "=T/F";
+  static cch_t   eng_zGnuBreak[] =
+       "\n\
+%s\n\n";
+  static char    eng_zGnuKeyArg[] =
+       "=KWd";
+  static char    eng_zGnuKeyLArg[] =
+       "=Mbr";
+  static cch_t   eng_zGnuNestArg[] =
+       "=Cplx";
+  static char    eng_zGnuNumArg[] =
+       "=num";
+  static cch_t   eng_zGnuOptArg[] =
+       "[=arg]";
+  static cch_t   eng_zGnuOptFmt[] =
+       "--%2$s%1$s";
+  static char    eng_zGnuStrArg[] =
+       "=str";
+  static cch_t   eng_zHomePath[] =
+       " - reading file /... %s's exe directory .../%s \n";
+  static cch_t   eng_zIllOptChr[] =
+       "%s: illegal option -- %c\n";
+  static cch_t   eng_zIllOptStr[] =
+       "%s: %s option -- %s\n";
+  static cch_t   eng_zIllegal[] =
+       "illegal";
+  static cch_t   eng_zInvalOptDesc[] =
+       "AutoOpts ERROR:  invalid option descriptor for %s\n";
+  static cch_t   eng_zKeyWords[] =
+       "words=";
+  static cch_t   eng_zLoadCooked[] =
+       "cooked";
+  static cch_t   eng_zLoadKeep[] =
+       "keep";
+  static cch_t   eng_zLoadType[] =
+       "type=";
+  static cch_t   eng_zLoadUncooked[] =
+       "uncooked";
+  static cch_t   eng_zLtypeInteger[] =
+       "integer";
+  static cch_t   eng_zLtypeNest[] =
+       "nested";
+  static cch_t   eng_zLtypeString[] =
+       "string";
+  static cch_t   eng_zLtypeBool[] =
+       "bool";
+  static cch_t   eng_zLtypeKeyword[] =
+       "keyword";
+  static cch_t   eng_zLtypeSetMembership[] =
+       "set";
+  static cch_t   eng_zMembers[] =
+       "\t\t\t\t- is a set membership option\n";
+  static cch_t   eng_zMisArg[] =
+       "%s: option `%s' requires an argument\n";
+  static cch_t   eng_zMultiEquiv[] =
+       "Equivalenced option '%s' was equivalenced to both\n\
+\t'%s' and '%s'";
+  static cch_t   eng_zMust[] =
+       "\t\t\t\t- must appear between %d and %d times\n";
+  static cch_t   eng_zNeedOne[] =
+       "ERROR:  The %s option is required\n";
+  static cch_t   eng_zNoArg[] =
+       "%s: option `%s' cannot have an argument\n";
+  static cch_t   eng_zNoArgs[] =
+       "%s: Command line arguments not allowed\n";
+  static cch_t   eng_zNoCreat[] =
+       "error %d (%s) creating %s\n";
+  static cch_t   eng_zNoFlags[] =
+       "Options are specified by single or double hyphens and their name.\n";
+  static cch_t   eng_zNoKey[] =
+       "%s error:  `%s' does not match any keywords\n";
+  static cch_t   eng_zNoLim[] =
+       "\t\t\t\t- may appear multiple times\n";
+  static cch_t   eng_zNoPreset[] =
+       "\t\t\t\t- may not be preset\n";
+  static cch_t   eng_zNoRq_NoShrtTtl[] =
+       "   Arg Option-Name    Description\n";
+  static cch_t   eng_zNoRq_ShrtTtl[] =
+       "  Flg Arg Option-Name    Description\n";
+  static cch_t   eng_zNoStat[] =
+       "error %d (%s) stat-ing %s\n";
+  static cch_t   eng_zNoState[] =
+       "%s(optionRestore): error: no saved option state\n";
+  static cch_t   eng_zNone[] =
+       "none";
+  static cch_t   eng_zNotDef[] =
+       "'%s' not defined\n";
+  static cch_t   eng_zNotEnough[] =
+       "ERROR:  The %s option must appear %d times\n";
+  static cch_t   eng_zNotFile[] =
+       "error:  cannot load options from non-regular file %s\n";
+  static cch_t   eng_zNotNumber[] =
+       "%s error:  `%s' is not a recognizable number\n";
+  static cch_t   eng_zNrmOptFmt[] =
+       " %3s %s";
+  static cch_t   eng_zNumberOpt[] =
+       "The '-#<number>' option may omit the hash char\n";
+  static cch_t   eng_zOneSpace[] =
+       " ";
+  static cch_t   eng_zOnlyOne[] =
+       "one %s%s option allowed\n";
+  static cch_t   eng_zOptsOnly[] =
+       "All arguments are named options.\n";
+  static cch_t   eng_zPathFmt[] =
+       " - reading file %s";
+  static cch_t   eng_zPlsSendBugs[] =
+       "\n\
+please send bug reports to:  %s\n";
+  static cch_t   eng_zPreset[] =
+       "\t\t\t\t- may NOT appear - preset only\n";
+  static cch_t   eng_zPresetFile[] =
+       "#  preset/initialization file\n\
+#  %s#\n";
+  static cch_t   eng_zPresetIntro[] =
+       "\n\
+The following option preset mechanisms are supported:\n";
+  static cch_t   eng_zProg[] =
+       "program";
+  static cch_t   eng_zProhib[] =
+       "prohibits these options:\n";
+  static cch_t   eng_zReorder[] =
+       "Operands and options may be intermixed.  They will be reordered.\n";
+  static cch_t   eng_zReqFmt[] =
+       "ERROR:  %s option requires the %s option\n";
+  static cch_t   eng_zReqOptFmt[] =
+       " %3s %-14s %s";
+  static cch_t   eng_zReqThese[] =
+       "requires these options:\n";
+  static cch_t   eng_zReq_NoShrtTtl[] =
+       "   Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zReq_ShrtTtl[] =
+       "  Flg Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zSepChars[] =
+       "-_^";
+  static cch_t   eng_zSetMembers[] =
+       "members=";
+  static cch_t   eng_zSetMemberSettings[] =
+       "or you may use a numeric representation.  Preceding these with a '!' will\n\
+clear the bits, specifying 'none' will clear all bits, and 'all' will set them\n\
+all.  Multiple entries may be passed as an option argument list.\n";
+  static cch_t   eng_zShrtGnuOptFmt[] =
+       "%s";
+  static cch_t   eng_zSixSpaces[] =
+       "      ";
+  static cch_t   eng_zStdBoolArg[] =
+       "T/F";
+  static cch_t   eng_zStdBreak[] =
+       "\n\
+%s\n\n\
+%s";
+  static cch_t   eng_zStdKeyArg[] =
+       "KWd";
+  static cch_t   eng_zStdKeyLArg[] =
+       "Mbr";
+  static cch_t   eng_zStdNestArg[] =
+       "Cpx";
+  static cch_t   eng_zStdNoArg[] =
+       "no ";
+  static cch_t   eng_zStdNumArg[] =
+       "Num";
+  static cch_t   eng_zStdOptArg[] =
+       "opt";
+  static cch_t   eng_zStdReqArg[] =
+       "YES";
+  static cch_t   eng_zStdStrArg[] =
+       "Str";
+  static cch_t   eng_zTabHyp[] =
+       "\t\t\t\t- ";
+  static cch_t   eng_zTabHypAnd[] =
+       "\t\t\t\t-- and ";
+  static cch_t   eng_zTabout[] =
+       "\t\t\t\t%s\n";
+  static cch_t   eng_zThreeSpaces[] =
+       "   ";
+  static cch_t   eng_zTwoSpaces[] =
+       "  ";
+  static cch_t   eng_zUpTo[] =
+       "\t\t\t\t- may appear up to %d times\n";
+  static cch_t   eng_zValidKeys[] =
+       "The valid \"%s\" option keywords are:\n";
+
+  /*
+   *  Now, define (and initialize) the structure that contains
+   *  the pointers to all these strings.
+   *  Aren't you glad you don't maintain this by hand?
+   */
+  usage_text_t option_usage_text = {
+    114,
+    eng_zGnuBoolArg, eng_zGnuKeyArg,  eng_zGnuKeyLArg, eng_zGnuNumArg,
+    eng_zGnuStrArg,
+    {
+      eng_zAO_Bad,             eng_zAO_Big,             eng_zAO_Err,
+      eng_zAO_Sml,             eng_zAll,                eng_zAlt,
+      eng_zAmbigKey,           eng_zAmbiguous,          eng_zArgsMust,
+      eng_zAtMost,             eng_zAuto,               eng_zBadPipe,
+      eng_zBadVerArg,          eng_zCantFmt,            eng_zCantSave,
+      eng_zDefaultOpt,         eng_zDis,                eng_zEnab,
+      eng_zEquiv,              eng_zErrOnly,            eng_zExamineFmt,
+      eng_zFiveSpaces,         eng_zFlagOkay,           eng_zFmtFmt,
+      eng_zForkFail,           eng_zFSErrOptLoad,       eng_zFSErrReadFile,
+      eng_zGenshell,           eng_zGnuBreak,           eng_zGnuNestArg,
+      eng_zGnuOptArg,          eng_zGnuOptFmt,          eng_zHomePath,
+      eng_zIllOptChr,          eng_zIllOptStr,          eng_zIllegal,
+      eng_zInvalOptDesc,       eng_zKeyWords,           eng_zLoadCooked,
+      eng_zLoadKeep,           eng_zLoadType,           eng_zLoadUncooked,
+      eng_zLtypeInteger,       eng_zLtypeNest,          eng_zLtypeString,
+      eng_zLtypeBool,          eng_zLtypeKeyword,       eng_zLtypeSetMembership,
+      eng_zMembers,            eng_zMisArg,             eng_zMultiEquiv,
+      eng_zMust,               eng_zNeedOne,            eng_zNoArg,
+      eng_zNoArgs,             eng_zNoCreat,            eng_zNoFlags,
+      eng_zNoKey,              eng_zNoLim,              eng_zNoPreset,
+      eng_zNoRq_NoShrtTtl,     eng_zNoRq_ShrtTtl,       eng_zNoStat,
+      eng_zNoState,            eng_zNone,               eng_zNotDef,
+      eng_zNotEnough,          eng_zNotFile,            eng_zNotNumber,
+      eng_zNrmOptFmt,          eng_zNumberOpt,          eng_zOneSpace,
+      eng_zOnlyOne,            eng_zOptsOnly,           eng_zPathFmt,
+      eng_zPlsSendBugs,        eng_zPreset,             eng_zPresetFile,
+      eng_zPresetIntro,        eng_zProg,               eng_zProhib,
+      eng_zReorder,            eng_zReqFmt,             eng_zReqOptFmt,
+      eng_zReqThese,           eng_zReq_NoShrtTtl,      eng_zReq_ShrtTtl,
+      eng_zSepChars,           eng_zSetMembers,         eng_zSetMemberSettings,
+      eng_zShrtGnuOptFmt,      eng_zSixSpaces,          eng_zStdBoolArg,
+      eng_zStdBreak,           eng_zStdKeyArg,          eng_zStdKeyLArg,
+      eng_zStdNestArg,         eng_zStdNoArg,           eng_zStdNumArg,
+      eng_zStdOptArg,          eng_zStdReqArg,          eng_zStdStrArg,
+      eng_zTabHyp,             eng_zTabHypAnd,          eng_zTabout,
+      eng_zThreeSpaces,        eng_zTwoSpaces,          eng_zUpTo,
+      eng_zValidKeys
+    }
+  };
+
+#endif /* DO_TRANSLATIONS */
+#endif /* AUTOOPTS_USAGE_TXT_H_GUARD */
diff --git a/sntp/libopts/boolean.c b/sntp/libopts/boolean.c
new file mode 100644 (file)
index 0000000..98bda0a
--- /dev/null
@@ -0,0 +1,102 @@
+
+/*
+ *  $Id: boolean.c,v 4.4 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-14 08:24:12 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionBooleanVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a true or false value for a boolean valued option argument.
+ *  The value is true, unless it starts with 'n' or 'f' or "#f" or
+ *  it is an empty string or it is a number that evaluates to zero.
+=*/
+void
+optionBooleanVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    long  val;
+    char* pz;
+    ag_bool  res = AG_TRUE;
+
+    switch (*(pOD->pzLastArg)) {
+    case '0':
+        val = strtol( pOD->pzLastArg, &pz, 0 );
+        if ((val != 0) || (*pz != NUL))
+            break;
+        /* FALLTHROUGH */
+    case 'N':
+    case 'n':
+    case 'F':
+    case 'f':
+    case NUL:
+        res = AG_FALSE;
+        break;
+    case '#':
+        if (pOD->pzLastArg[1] != 'f')
+            break;
+        res = AG_FALSE;
+    }
+
+    pOD->pzLastArg = (char*)res;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/boolean.c */
diff --git a/sntp/libopts/compat/compat.h b/sntp/libopts/compat/compat.h
new file mode 100644 (file)
index 0000000..f9c109b
--- /dev/null
@@ -0,0 +1,249 @@
+/*  -*- Mode: C -*-  */
+
+/* --- fake the preprocessor into handlng portability */
+/*
+ *  Time-stamp:      "2005-06-26 08:18:00 bkorb"
+ *
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Mon Jun 30 15:54:46 1997
+ *
+ * $Id: compat.h,v 4.4 2005/06/26 16:26:45 bkorb Exp $
+ */
+#ifndef COMPAT_H
+#define COMPAT_H 1
+
+#ifndef HAVE_CONFIG_H
+#  error "compat.h" requires "config.h"
+#endif
+
+#include <config.h>
+
+#ifndef HAVE_STRSIGNAL
+   char * strsignal( int signo );
+#else
+#  define  _GNU_SOURCE /* for strsignal in GNU's libc */
+#  define  __USE_GNU   /* exact same thing as above   */
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  SYSTEM HEADERS:
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#if HAVE_SYS_PROCSET_H
+#  include <sys/procset.h>
+#endif
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#if defined( HAVE_POSIX_SYSINFO )
+#  include <sys/systeminfo.h>
+#elif defined( HAVE_UNAME_SYSCALL )
+#  include <sys/utsname.h>
+#endif
+
+#ifdef DAEMON_ENABLED
+#  if HAVE_SYS_STROPTS_H
+#  include <sys/stropts.h>
+#  endif
+
+#  if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#  endif
+
+#  if ! defined(HAVE_SYS_POLL_H) && ! defined(HAVE_SYS_SELECT_H)
+#    error This system cannot support daemon processing
+#  endif
+
+#  if HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+#  endif
+
+#  if HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+#  endif
+
+#  if HAVE_NETINET_IN_H
+#  include <netinet/in.h>
+#  endif
+
+#  if HAVE_SYS_UN_H
+#  include <sys/un.h>
+#  endif
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  USER HEADERS:
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+/*
+ *  Directory opening stuff:
+ */
+# if defined (_POSIX_SOURCE)
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+#    define REAL_DIR_ENTRY(dp) 1
+# else /* !_POSIX_SOURCE */
+#    define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# endif /* !_POSIX_SOURCE */
+
+# if defined (HAVE_DIRENT_H)
+#   include <dirent.h>
+#   define D_NAMLEN(dirent) strlen((dirent)->d_name)
+# else /* !HAVE_DIRENT_H */
+#   define dirent direct
+#   define D_NAMLEN(dirent) (dirent)->d_namlen
+#   if defined (HAVE_SYS_NDIR_H)
+#     include <sys/ndir.h>
+#   endif /* HAVE_SYS_NDIR_H */
+#   if defined (HAVE_SYS_DIR_H)
+#     include <sys/dir.h>
+#   endif /* HAVE_SYS_DIR_H */
+#   if defined (HAVE_NDIR_H)
+#     include <ndir.h>
+#   endif /* HAVE_NDIR_H */
+# endif /* !HAVE_DIRENT_H */
+
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK FNDELAY
+#endif
+
+#if defined(HAVE_LIBGEN) && defined(HAVE_LIBGEN_H)
+#  include <libgen.h>
+#endif
+
+#include <limits.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#if defined( HAVE_STDINT_H )
+#  include <stdint.h>
+#elif defined( HAVE_INTTYPES_H )
+#  include <inttypes.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+#include <utime.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FIXUPS and CONVIENCE STUFF:
+ */
+#ifdef __cplusplus
+#   define EXTERN extern "C"
+#else
+#   define EXTERN extern
+#endif
+
+/* some systems #def errno! and others do not declare it!! */
+#ifndef errno
+   extern int errno;
+#endif
+
+/* Some machines forget this! */
+
+# ifndef EXIT_FAILURE
+#   define EXIT_SUCCESS 0
+#   define EXIT_FAILURE 1
+# endif
+
+#ifndef NUL
+#  define NUL '\0'
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+#if !defined (MAXPATHLEN) && defined (HAVE_SYS_PARAM_H)
+#  include <sys/param.h>
+#endif /* !MAXPATHLEN && HAVE_SYS_PARAM_H */
+
+#if !defined (MAXPATHLEN) && defined (PATH_MAX)
+#  define MAXPATHLEN PATH_MAX
+#endif /* !MAXPATHLEN && PATH_MAX */
+
+#if !defined (MAXPATHLEN)
+#  define MAXPATHLEN 4096
+#endif /* MAXPATHLEN */
+
+# ifndef LONG_MAX
+#   define LONG_MAX     ~(1L << (8*sizeof(long) -1))
+#   define INT_MAX      ~(1 << (8*sizeof(int) -1))
+#   define SHORT_MAX    ~(1 << (8*sizeof(short) -1))
+# endif
+
+# ifndef ULONG_MAX
+#   define ULONG_MAX    ~(OUL)
+#   define UINT_MAX     ~(OU)
+#   define USHORT_MAX   ~(OUS)
+# endif
+
+/* redefine these for BSD style string libraries */
+#ifndef HAVE_STRCHR
+#  define strchr        index
+#  define strrchr       rindex
+#endif
+
+#ifdef USE_FOPEN_BINARY
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG   "b"
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG     "t"
+#  endif
+#else
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG
+#  endif
+#endif
+
+#ifndef STR
+#  define _STR(s) #s
+#  define STR(s)  _STR(s)
+#endif
+
+/* ##### Pointer sized word ##### */
+
+/* FIXME:  the MAX stuff in here is broken! */
+#if SIZEOF_CHARP > SIZEOF_INT
+   typedef long t_word;
+   #define WORD_MAX  LONG_MAX
+   #define WORD_MIN  LONG_MIN
+#else /* SIZEOF_CHARP <= SIZEOF_INT */
+   typedef int t_word;
+   #define WORD_MAX  INT_MAX
+   #define WORD_MIN  INT_MIN
+#endif
+
+#endif /* COMPAT_H */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/compat.h */
diff --git a/sntp/libopts/compat/pathfind.c b/sntp/libopts/compat/pathfind.c
new file mode 100644 (file)
index 0000000..4da759f
--- /dev/null
@@ -0,0 +1,330 @@
+/*  -*- Mode: C -*-  */
+
+/* pathfind.c --- find a FILE  MODE along PATH */
+
+/*
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Tue Jun 24 15:07:31 1997
+ * Last Modified:    $Date: 2005/07/27 17:26:32 $
+ *            by: bkorb
+ *
+ * $Id: pathfind.c,v 4.4 2005/07/27 17:26:32 bkorb Exp $
+ */
+
+/* Code: */
+
+#include "compat.h"
+#ifndef HAVE_PATHFIND
+
+static char* make_absolute( const char *string, const char *dot_path );
+static char* canonicalize_pathname( char *path );
+static char* extract_colon_unit( char* dir, const char *string, int *p_index );
+
+
+/*=export_func pathfind
+ *
+ * what: fild a file in a list of directories
+ *
+ * ifndef: HAVE_PATHFIND
+ *
+ * arg:  + const char* + path + colon separated list of search directories +
+ * arg:  + const char* + file + the name of the file to look for +
+ * arg:  + const char* + mode + the mode bits that must be set to match +
+ *
+ * ret_type:  char*
+ * ret_desc:  the path to the located file
+ *
+ * doc:
+ *
+ * pathfind looks for a a file with name "FILE" and "MODE" access
+ * along colon delimited "PATH", and returns the full pathname as a
+ * string, or NULL if not found.  If "FILE" contains a slash, then
+ * it is treated as a relative or absolute path and "PATH" is ignored.
+ *
+ * @strong{NOTE}: this function is compiled into @file{libopts} only if
+ * it is not natively supplied.
+ *
+ * The "MODE" argument is a string of option letters chosen from the
+ * list below:
+ * @example
+ *          Letter    Meaning
+ *          r         readable
+ *          w         writable
+ *          x         executable
+ *          f         normal file       (NOT IMPLEMENTED)
+ *          b         block special     (NOT IMPLEMENTED)
+ *          c         character special (NOT IMPLEMENTED)
+ *          d         directory         (NOT IMPLEMENTED)
+ *          p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *          u         set user ID bit   (NOT IMPLEMENTED)
+ *          g         set group ID bit  (NOT IMPLEMENTED)
+ *          k         sticky bit        (NOT IMPLEMENTED)
+ *          s         size nonzero      (NOT IMPLEMENTED)
+ * @end example
+ *
+ * example:
+ * To find the "ls" command using the "PATH" environment variable:
+ * @example
+ *    #include <stdlib.h>
+ *    char* pz_ls = pathfind( getenv("PATH"), "ls", "rx" );
+ *    <<do whatever with pz_ls>>
+ *    free( pz_ls );
+ * @end example
+ * The path is allocated with @code{malloc(3C)}, so you must @code{free(3C)}
+ * the result.  Also, do not use unimplemented file modes.  :-)
+ *
+ * err:  returns NULL if the file is not found.
+=*/
+char*
+pathfind( const char*  path,
+          const char*  fileName,
+          const char*  mode )
+{
+    int   p_index   = 0;
+    int   mode_bits = 0;
+    char* pathName  = NULL;
+    char  zPath[ MAXPATHLEN + 1 ];
+
+    if (strchr( mode, 'r' )) mode_bits |= R_OK;
+    if (strchr( mode, 'w' )) mode_bits |= W_OK;
+    if (strchr( mode, 'x' )) mode_bits |= X_OK;
+
+    /*
+     *  FOR each non-null entry in the colon-separated path, DO ...
+     */
+    for (;;) {
+        DIR*  dirP;
+        char* colon_unit = extract_colon_unit( zPath, path, &p_index );
+
+        /*
+         *  IF no more entries, THEN quit
+         */
+        if (colon_unit == NULL)
+            break;
+
+        dirP = opendir( colon_unit );
+
+        /*
+         *  IF the directory is inaccessable, THEN next directory
+         */
+        if (dirP == NULL)
+            continue;
+
+        /*
+         *  FOR every entry in the given directory, ...
+         */
+        for (;;) {
+            struct dirent *entP = readdir( dirP );
+
+            if (entP == (struct dirent*)NULL)
+                break;
+
+            /*
+             *  IF the file name matches the one we are looking for, ...
+             */
+            if (strcmp( entP->d_name, fileName ) == 0) {
+                char* pzFullName = make_absolute( fileName, colon_unit);
+
+                /*
+                 *  Make sure we can access it in the way we want
+                 */
+                if (access( pzFullName, mode_bits ) >= 0) {
+                    /*
+                     *  We can, so normalize the name and return it below
+                     */
+                    pathName = canonicalize_pathname( pzFullName );
+                }
+
+                free( (void*)pzFullName );
+                break;
+            }
+        }
+        
+        closedir( dirP );
+
+        if (pathName != NULL)
+            break;
+    }
+
+    return pathName;
+}
+
+/*
+ * Turn STRING  (a pathname) into an  absolute  pathname, assuming  that
+ * DOT_PATH contains the symbolic location of  `.'.  This always returns
+ * a new string, even if STRING was an absolute pathname to begin with.
+ */
+static char*
+make_absolute( const char *string, const char *dot_path )
+{
+    char *result;
+    int result_len;
+  
+    if (!dot_path || *string == '/') {
+        result = strdup( string );
+    } else {
+        if (dot_path && dot_path[0]) {
+            result = malloc( 2 + strlen( dot_path ) + strlen( string ) );
+            strcpy( result, dot_path );
+            result_len = strlen( result );
+            if (result[result_len - 1] != '/') {
+                result[result_len++] = '/';
+                result[result_len] = '\0';
+            }    
+        } else {
+            result = malloc( 3 + strlen( string ) );
+            result[0] = '.'; result[1] = '/'; result[2] = '\0';
+            result_len = 2;
+        }
+
+        strcpy( result + result_len, string );
+    }
+
+    return result;
+}
+
+/*
+ * Canonicalize PATH, and return a  new path.  The new path differs from
+ * PATH in that:
+ *
+ *    Multiple `/'s     are collapsed to a single `/'.
+ *    Leading `./'s     are removed.
+ *    Trailing `/.'s    are removed.
+ *    Trailing `/'s     are removed.
+ *    Non-leading `../'s and trailing `..'s are handled by removing
+ *                    portions of the path.
+ */
+static char*
+canonicalize_pathname( char *path )
+{
+    int i, start;
+    char stub_char, *result;
+
+    /* The result cannot be larger than the input PATH. */
+    result = strdup( path );
+
+    stub_char = (*path == '/') ? '/' : '.';
+
+    /* Walk along RESULT looking for things to compact. */
+    i = 0;
+    while (result[i]) {
+        while (result[i] != '\0' && result[i] != '/')
+            i++;
+
+        start = i++;
+
+        /* If we didn't find any  slashes, then there is nothing left to
+         * do.
+         */
+        if (!result[start])
+            break;
+
+        /* Handle multiple `/'s in a row. */
+        while (result[i] == '/')
+            i++;
+
+#if !defined (apollo)
+        if ((start + 1) != i)
+#else
+        if ((start + 1) != i && (start != 0 || i != 2))
+#endif /* apollo */
+        {
+            strcpy( result + start + 1, result + i );
+            i = start + 1;
+        }
+
+        /* Handle backquoted `/'. */
+        if (start > 0 && result[start - 1] == '\\')
+            continue;
+
+        /* Check for trailing `/', and `.' by itself. */
+        if ((start && !result[i])
+            || (result[i] == '.' && !result[i+1])) {
+            result[--i] = '\0';
+            break;
+        }
+
+        /* Check for `../', `./' or trailing `.' by itself. */
+        if (result[i] == '.') {
+            /* Handle `./'. */
+            if (result[i + 1] == '/') {
+                strcpy( result + i, result + i + 1 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+
+            /* Handle `../' or trailing `..' by itself. */
+            if (result[i + 1] == '.' &&
+                (result[i + 2] == '/' || !result[i + 2])) {
+                while (--start > -1 && result[start] != '/')
+                    ;
+                strcpy( result + start + 1, result + i + 2 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+        }
+    }
+
+    if (!*result) {
+        *result = stub_char;
+        result[1] = '\0';
+    }
+
+    return result;
+}
+
+/*
+ * Given a  string containing units of information separated  by colons,
+ * return the next one  pointed to by (P_INDEX), or NULL if there are no
+ * more.  Advance (P_INDEX) to the character after the colon.
+ */
+static char*
+extract_colon_unit( char* pzDir, const char *string, int *p_index )
+{
+    char*  pzDest = pzDir;
+    int    ix     = *p_index;
+
+    if (string == NULL)
+        return NULL;
+
+    if ((unsigned)ix >= strlen( string ))
+        return NULL;
+
+    {
+        const char* pzSrc = string + ix;
+
+        while (*pzSrc == ':')  pzSrc++;
+
+        for (;;) {
+            char ch = (*(pzDest++) = *(pzSrc++));
+            switch (ch) {
+            case ':':
+                pzDest[-1] = NUL;
+            case NUL:
+                goto copy_done;
+            }
+
+            if ((pzDest - pzDir) >= MAXPATHLEN)
+                break;
+        } copy_done:;
+
+        ix = pzSrc - string;
+    }
+
+    if (*pzDir == NUL)
+        return NULL;
+
+    *p_index = ix;
+    return pzDir;
+}
+
+#endif /* HAVE_PATHFIND */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/pathfind.c */
diff --git a/sntp/libopts/configfile.c b/sntp/libopts/configfile.c
new file mode 100644 (file)
index 0000000..522e583
--- /dev/null
@@ -0,0 +1,1277 @@
+/*
+ *  $Id: configfile.c,v 4.10 2005/07/27 17:26:32 bkorb Exp $
+ *  Time-stamp:      "2005-07-27 10:09:29 bkorb"
+ *
+ *  configuration/rc/ini file handling.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction );
+
+static char*
+handleComment( char* pzText );
+
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode );
+
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+skipUnknown( char* pzText );
+/* = = = END-STATIC-FORWARD = = = */
+
+
+/*=export_func  configFileLoad
+ *
+ * what:  parse a configuration file
+ * arg:   + const char*     + pzFile + the file to load +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ *
+ * err:
+ *  If the file cannot be loaded or processed, @code{NULL} is returned and
+ *  @var{errno} is set.  It may be set by a call to either @code{open(2)}
+ *  @code{mmap(2)} or other file system calls, or it may be:
+ *  @itemize @bullet
+ *  @item
+ *  @code{ENOENT} - the file was empty.
+ *  @item
+ *  @code{EINVAL} - the file contents are invalid -- not properly formed.
+ *  @item
+ *  @code{ENOMEM} - not enough memory to allocate the needed structures.
+ *  @end itemize
+=*/
+const tOptionValue*
+configFileLoad( const char* pzFile )
+{
+    tmap_info_t   cfgfile;
+    tOptionValue* pRes = NULL;
+    char* pzText =
+        text_mmap( pzFile, PROT_READ, MAP_PRIVATE, &cfgfile );
+
+    if (pzText == MAP_FAILED)
+        return NULL; /* errno is set */
+
+    pRes = optionLoadNested(pzText, pzFile, strlen(pzFile), OPTION_LOAD_COOKED);
+
+    if (pRes == NULL) {
+        int err = errno;
+        text_munmap( &cfgfile );
+        errno = err;
+    } else
+        text_munmap( &cfgfile );
+    return pRes;
+}
+
+
+/*=export_func  optionFindValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindValue( const tOptDesc* pOptDesc,
+                 const char* pzName, const char* pzVal )
+{
+    const tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        const tOptionValue** ppOV =
+            (const tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        if (pzName == NULL) {
+            pRes = *ppOV;
+            break;
+        }
+
+        while (--ct >= 0) {
+            const tOptionValue* pOV = *(ppOV++);
+            const tOptionValue* pRV = optionGetValue( pOV, pzName );
+
+            if (pRV == NULL)
+                continue;
+
+            if (pzVal == NULL) {
+                pRes = pOV;
+                break;
+            }
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionFindNextValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const tOptionValue* + pPrevVal + the last entry +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindNextValue( const tOptDesc* pOptDesc, const tOptionValue* pPrevVal,
+                 const char* pzName, const char* pzVal )
+{
+    int foundOldVal = 0;
+    tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        tOptionValue** ppOV = (tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        while (--ct >= 0) {
+            tOptionValue* pOV = *(ppOV++);
+            if (foundOldVal) {
+                pRes = pOV;
+                break;
+            }
+            if (pOV == pPrevVal)
+                foundOldVal = 1;
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionGetValue
+ *
+ * what:  get a specific value from a hierarcical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal value +
+ * arg:   + const char*   + valueName + name of value to get +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionGetValue( const tOptionValue* pOld, const char* pzValName )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+
+    if ((pOld == NULL) || (pOld->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOld->v.nestVal;
+
+    if (pAL->useCt > 0) {
+        int ct = pAL->useCt;
+        tOptionValue** papOV = (tOptionValue**)(pAL->apzArgs);
+
+        if (pzValName == NULL) {
+            pRes = *papOV;
+        }
+
+        else do {
+            tOptionValue* pOV = *(papOV++);
+            if (strcmp( pOV->pzName, pzValName ) == 0) {
+                pRes = pOV;
+                break;
+            }
+        } while (--ct > 0);
+    }
+    if (pRes == NULL)
+        errno = ENOENT;
+    return pRes;
+}
+
+
+/*=export_func  optionNextValue
+ *
+ * what:  get the next value from a hierarchical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal list value +
+ * arg:   + const tOptionValue* + pOldValue + a value from this list   +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value or @code{pOldValue} does not point to a
+ *  member of that option value.
+ *  @item
+ *  @code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionNextValue( const tOptionValue* pOVList, const tOptionValue* pOldOV )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+    int           err  = EINVAL;
+
+    if ((pOVList == NULL) || (pOVList->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOVList->v.nestVal;
+    {
+        int   ct   = pAL->useCt;
+        tOptionValue** papNV = (tOptionValue**)(pAL->apzArgs);
+
+        while (ct-- > 0) {
+            tOptionValue* pNV = *(papNV++);
+            if (pNV == pOldOV) {
+                if (ct == 0) {
+                    err = ENOENT;
+
+                } else {
+                    err  = 0;
+                    pRes = *papNV;
+                }
+                break;
+            }
+        }
+    }
+    if (err != 0)
+        errno = err;
+    return pRes;
+}
+
+
+/*  filePreset
+ *
+ *  Load a file containing presetting information (a configuration file).
+ */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction )
+{
+    tmap_info_t   cfgfile;
+    char*         pzFileText =
+        text_mmap( pzFileName, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile );
+    tOptState     st = OPTSTATE_INITIALIZER(PRESET);
+
+    if (pzFileText == MAP_FAILED)
+        return;
+
+    if (direction == DIRECTION_CALLED) {
+        st.flags  = OPTST_DEFINED;
+        direction = DIRECTION_PROCESS;
+    }
+
+    /*
+     *  IF this is called via "optionProcess", then we are presetting.
+     *  This is the default and the PRESETTING bit will be set.
+     *  If this is called via "optionFileLoad", then the bit is not set
+     *  and we consider stuff set herein to be "set" by the client program.
+     */
+    if ((pOpts->fOptSet & OPTPROC_PRESETTING) == 0)
+        st.flags = OPTST_SET;
+
+    do  {
+        while (isspace( *pzFileText ))  pzFileText++;
+
+        if (isalpha( *pzFileText )) {
+            pzFileText = handleConfig( pOpts, &st, pzFileText, direction );
+
+        } else switch (*pzFileText) {
+        case '<':
+            if (isalpha( pzFileText[1] ))
+                pzFileText = handleStructure(pOpts, &st, pzFileText, direction);
+
+            else switch (pzFileText[1]) {
+            case '?':
+                pzFileText = handleDirective( pOpts, pzFileText );
+                break;
+
+            case '!':
+                pzFileText = handleComment( pzFileText );
+                break;
+
+            case '/':
+                pzFileText = strchr( pzFileText+2, '>' );
+                if (pzFileText++ != NULL)
+                    break;
+
+            default:
+                goto all_done;
+            }
+            break;
+
+        case '[':
+            pzFileText = handleProgramSection( pOpts, pzFileText );
+            break;
+
+        case '#':
+            pzFileText = strchr( pzFileText+1, '\n' );
+            break;
+
+        default:
+            goto all_done; /* invalid format */
+        }
+    } while (pzFileText != NULL);
+
+ all_done:
+    text_munmap( &cfgfile );
+}
+
+
+/*  handleComment
+ *
+ *  "pzText" points to a "<!" sequence.
+ *  Theoretically, we should ensure that it begins with "<!--",
+ *  but actually I don't care that much.  It ends with "-->".
+ */
+static char*
+handleComment( char* pzText )
+{
+    char* pz = strstr( pzText, "-->" );
+    if (pz != NULL)
+        pz += 3;
+    return pz;
+}
+
+
+/*  handleConfig
+ *
+ *  "pzText" points to the start of some value name.
+ *  The end of the entry is the end of the line that is not preceded by
+ *  a backslash escape character.  The string value is always processed
+ *  in "cooked" mode.
+ */
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    char* pzName = pzText++;
+    char* pzEnd  = strchr( pzText, '\n' );
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    while (isspace( *pzText )) pzText++;
+    if (pzText > pzEnd) {
+    name_only:
+        *pzEnd++ = NUL;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+        return pzEnd;
+    }
+
+    /*
+     *  Either the first character after the name is a ':' or '=',
+     *  or else we must have skipped over white space.  Anything else
+     *  is an invalid format and we give up parsing the text.
+     */
+    if ((*pzText == '=') || (*pzText == ':')) {
+        while (isspace( *++pzText ))   ;
+        if (pzText > pzEnd)
+            goto name_only;
+    } else if (! isspace(pzText[-1]))
+        return NULL;
+
+    /*
+     *  IF the value is continued, remove the backslash escape and push "pzEnd"
+     *  on to a newline *not* preceded by a backslash.
+     */
+    if (pzEnd[-1] == '\\') {
+        char* pcD = pzEnd-1;
+        char* pcS = pzEnd;
+
+        for (;;) {
+            char ch = *(pcS++);
+            switch (ch) {
+            case NUL:
+                pcS = NULL;
+
+            case '\n':
+                *pcD = NUL;
+                pzEnd = pcS;
+                goto copy_done;
+
+            case '\\':
+                if (*pcS == '\n') {
+                    ch = *(pcS++);
+                }
+                /* FALLTHROUGH */
+            default:
+                *(pcD++) = ch;
+            }
+        } copy_done:;
+
+    } else {
+        /*
+         *  The newline was not preceded by a backslash.  NUL it out
+         */
+        *(pzEnd++) = NUL;
+    }
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+
+    return pzEnd;
+}
+
+
+/*  handleDirective
+ *
+ *  "pzText" points to a "<?" sequence.
+ *  For the moment, we only handle "<?program" directives.
+ */
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    char   ztitle[32] = "<?";
+    size_t title_len = strlen( zProg );
+    size_t name_len;
+
+    if (  (strncmp( pzText+2, zProg, title_len ) != 0)
+       || (! isspace( pzText[title_len+2] )) )  {
+        pzText = strchr( pzText+2, '>' );
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    name_len = strlen( pOpts->pzProgName );
+    strcpy( ztitle+2, zProg );
+    title_len += 2;
+
+    do  {
+        pzText += title_len;
+
+        if (isspace(*pzText)) {
+            while (isspace(*pzText))  pzText++;
+            if (  (strneqvcmp( pzText, pOpts->pzProgName, name_len ) == 0)
+               && (pzText[name_len] == '>'))  {
+                pzText += name_len + 1;
+                break;
+            }
+        }
+
+        pzText = strstr( pzText, ztitle );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  handleProgramSection
+ *
+ *  "pzText" points to a '[' character.
+ *  The "traditional" [PROG_NAME] segmentation of the config file.
+ *  Do not ever mix with the "<?program prog-name>" variation.
+ */
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    size_t len = strlen( pOpts->pzPROGNAME );
+    if (   (strncmp( pzText+1, pOpts->pzPROGNAME, len ) == 0)
+        && (pzText[len+1] == ']'))
+        return strchr( pzText + len + 2, '\n' );
+
+    if (len > 16)
+        return NULL;
+
+    {
+        char z[24];
+        sprintf( z, "[%s]", pOpts->pzPROGNAME );
+        pzText = strstr( pzText, z );
+    }
+
+    if (pzText != NULL)
+        pzText = strchr( pzText, '\n' );
+    return pzText;
+}
+
+
+/*  handleStructure
+ *
+ *  "pzText" points to a '<' character, followed by an alpha.
+ *  The end of the entry is either the "/>" following the name, or else a
+ *  "</name>" string.
+ */
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    tOptionLoadMode mode = OPTION_LOAD_UNCOOKED;
+    tOptionValue     valu;
+
+    char* pzName = ++pzText;
+    char* pcNulPoint;
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    pcNulPoint = pzText;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzText) {
+    case ' ':
+    case '\t':
+        pzText = parseAttributes( pOpts, pzText, &mode, &valu );
+        if (*pzText == '>')
+            break;
+        if (*pzText != '/')
+            return NULL;
+
+    case '/':
+        if (pzText[1] != '>')
+            return NULL;
+        *pzText = NUL;
+        pzText += 2;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_KEEP );
+        return pzText;
+
+    case '>':
+        break;
+
+    default:
+        pzText = strchr( pzText, '>');
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    /*
+     *  If we are here, we have a value.  Separate the name from the
+     *  value for a moment.
+     */
+    *pcNulPoint = NUL;
+
+    /*
+     *  Find the end of the option text and NUL terminate it
+     */
+    {
+        char   z[64], *pz = z;
+        size_t len = strlen(pzName) + 4;
+        if (len > sizeof(z))
+            pz = AGALOC(len, "scan name");
+
+        sprintf( pz, "</%s>", pzName );
+        *pzText = ' ';
+        pzText = strstr( pzText, pz );
+        if (pz != z) free(pz);
+
+        if (pzText == NULL)
+            return pzText;
+
+        *pzText = NUL;
+
+        pzText += len-1;
+    }
+
+    /*
+     *  Rejoin the name and value for parsing by "loadOptionLine()".
+     */
+    *(pcNulPoint++) = ' ';
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, mode );
+
+    return pzText;
+}
+
+
+/*  internalFileLoad
+ *
+ *  Load a configuration file.  This may be invoked either from
+ *  scanning the "homerc" list, or from a specific file request.
+ *  (see "optionFileLoad()", the implementation for --load-opts)
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts )
+{
+    int     idx;
+    int     inc = DIRECTION_PRESET;
+    char    zFileName[ MAXPATHLEN+1 ];
+
+    if (pOpts->papzHomeList == NULL)
+        return;
+
+    /*
+     *  Find the last RC entry (highest priority entry)
+     */
+    for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx)  ;
+
+    /*
+     *  For every path in the home list, ...  *TWICE* We start at the last
+     *  (highest priority) entry, work our way down to the lowest priority,
+     *  handling the immediate options.
+     *  Then we go back up, doing the normal options.
+     */
+    for (;;) {
+        struct stat StatBuf;
+        cch_t*  pzPath;
+
+        /*
+         *  IF we've reached the bottom end, change direction
+         */
+        if (idx < 0) {
+            inc = DIRECTION_PROCESS;
+            idx = 0;
+        }
+
+        pzPath = pOpts->papzHomeList[ idx ];
+
+        /*
+         *  IF we've reached the top end, bail out
+         */
+        if (pzPath == NULL)
+            break;
+
+        idx += inc;
+
+        if (! optionMakePath( zFileName, sizeof( zFileName ),
+                              pzPath, pOpts->pzProgPath ))
+            continue;
+
+        /*
+         *  IF the file name we constructed is a directory,
+         *  THEN append the Resource Configuration file name
+         *  ELSE we must have the complete file name
+         */
+        if (stat( zFileName, &StatBuf ) != 0)
+            continue; /* bogus name - skip the home list entry */
+
+        if (S_ISDIR( StatBuf.st_mode )) {
+            size_t len = strlen( zFileName );
+            char* pz;
+
+            if (len + 1 + strlen( pOpts->pzRcName ) >= sizeof( zFileName ))
+                continue;
+
+            pz = zFileName + len;
+            if (pz[-1] != '/')
+                *(pz++) = '/';
+            strcpy( pz, pOpts->pzRcName );
+        }
+
+        filePreset( pOpts, zFileName, inc );
+
+        /*
+         *  IF we are now to skip config files AND we are presetting,
+         *  THEN change direction.  We must go the other way.
+         */
+        if (SKIP_RC_FILES(pOpts) && PRESETTING(inc)) {
+            idx -= inc;  /* go back and reprocess current file */
+            inc =  DIRECTION_PROCESS;
+        }
+    } /* For every path in the home list, ... */
+}
+
+
+/*=export_func optionFileLoad
+ *
+ * what: Load the locatable config files, in order
+ *
+ * arg:  + tOptions*   + pOpts  + program options descriptor +
+ * arg:  + const char* + pzProg + program name +
+ *
+ * ret_type:  int
+ * ret_desc:  0 -> SUCCESS, -1 -> FAILURE
+ *
+ * doc:
+ *
+ * This function looks in all the specified directories for a configuration
+ * file ("rc" file or "ini" file) and processes any found twice.  The first
+ * time through, they are processed in reverse order (last file first).  At
+ * that time, only "immediate action" configurables are processed.  For
+ * example, if the last named file specifies not processing any more
+ * configuration files, then no more configuration files will be processed.
+ * Such an option in the @strong{first} named directory will have no effect.
+ *
+ * Once the immediate action configurables have been handled, then the
+ * directories are handled in normal, forward order.  In that way, later
+ * config files can override the settings of earlier config files.
+ *
+ * See the AutoOpts documentation for a thorough discussion of the
+ * config file format.
+ *
+ * Configuration files not found or not decipherable are simply ignored.
+ *
+ * err:  Returns the value, "-1" if the program options descriptor
+ *       is out of date or indecipherable.  Otherwise, the value "0" will
+ *       always be returned.
+=*/
+int
+optionFileLoad( tOptions* pOpts, const char* pzProgram )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, pzProgram )))
+        return -1;
+
+    pOpts->pzProgName = pzProgram;
+    internalFileLoad( pOpts );
+    return 0;
+}
+
+
+/*=export_func  optionLoadOpt
+ * private:
+ *
+ * what:  Load an option rc/ini file
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Processes the options found in the file named with pOptDesc->pzLastArg.
+=*/
+void
+optionLoadOpt( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    /*
+     *  IF the option is not being disabled,
+     *  THEN load the file.  There must be a file.
+     *  (If it is being disabled, then the disablement processing
+     *  already took place.  It must be done to suppress preloading
+     *  of ini/rc files.)
+     */
+    if (! DISABLED_OPT( pOptDesc )) {
+        struct stat sb;
+        if (stat( pOptDesc->pzLastArg, &sb ) != 0) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zFSErrOptLoad, errno, strerror( errno ),
+                     pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zNotFile, pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        filePreset(pOpts, pOptDesc->pzLastArg, DIRECTION_CALLED);
+    }
+}
+
+
+/*  parseAttributes
+ *
+ *  Parse the various attributes of an XML-styled config file entry
+ */
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType )
+{
+    size_t lenLoadType = strlen( zLoadType );
+    size_t lenKeyWords = strlen( zKeyWords );
+    size_t lenSetMem   = strlen( zSetMembers );
+
+    do  {
+        switch (*pzText) {
+        case '/': pType->valType = OPARG_TYPE_NONE;
+        case '>': return pzText;
+
+        default:
+        case NUL: return NULL;
+
+        case ' ':
+        case '\t':
+        case '\n':
+        case '\f':
+        case '\r':
+        case '\v':
+            break;
+        }
+
+        while (isspace( *++pzText ))   ;
+
+        if (strncmp( pzText, zLoadType, lenLoadType ) == 0) {
+            pzText = parseValueType( pzText+lenLoadType, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zKeyWords, lenKeyWords ) == 0) {
+            pzText = parseKeyWordType( pOpts, pzText+lenKeyWords, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zSetMembers, lenSetMem ) == 0) {
+            pzText = parseSetMemType( pOpts, pzText+lenSetMem, pType );
+            continue;
+        }
+
+        pzText = parseLoadMode( pzText, pMode );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  parseKeyWordType
+ *
+ *  "pzText" points to the character after "words=".
+ *  What should follow is a name of a keyword (enumeration) list.
+ */
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseLoadMode
+ *
+ *  "pzText" points to some name character.  We check for "cooked" or
+ *  "uncooked" or "keep".  This function should handle any attribute
+ *  that does not have an associated value.
+ */
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode )
+{
+    {
+        size_t len = strlen(zLoadCooked);
+        if (strncmp( pzText, zLoadCooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_COOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadUncooked);
+        if (strncmp( pzText, zLoadUncooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_UNCOOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadKeep);
+        if (strncmp( pzText, zLoadKeep, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_KEEP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    return skipUnknown( pzText );
+}
+
+
+/*  parseSetMemType
+ *
+ *  "pzText" points to the character after "members="
+ *  What should follow is a name of a "set membership".
+ *  A collection of bit flags.
+ */
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseValueType
+ *
+ *  "pzText" points to the character after "type="
+ */
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType )
+{
+    {
+        size_t len = strlen(zLtypeString);
+        if (strncmp( pzText, zLtypeString, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_STRING;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeInteger);
+        if (strncmp( pzText, zLtypeInteger, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_NUMERIC;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeBool);
+        if (strncmp( pzText, zLtypeBool, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_BOOLEAN;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeKeyword);
+        if (strncmp( pzText, zLtypeKeyword, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_ENUMERATION;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeSetMembership);
+        if (strncmp( pzText, zLtypeSetMembership, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_MEMBERSHIP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeNest);
+        if (strncmp( pzText, zLtypeNest, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_HIERARCHY;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    pType->valType = OPARG_TYPE_NONE;
+    return skipUnknown( pzText );
+}
+
+
+/*  skipUnknown
+ *
+ *  Skip over some unknown attribute
+ */
+static char*
+skipUnknown( char* pzText )
+{
+    for (;; pzText++) {
+        if (isspace( *pzText ))  return pzText;
+        switch (*pzText) {
+        case NUL: return NULL;
+        case '/':
+        case '>': return pzText;
+        }
+    }
+}
+
+
+/*  validateOptionsStruct
+ *
+ *  Make sure the option descriptor is there and that we understand it.
+ *  This should be called from any user entry point where one needs to
+ *  worry about validity.  (Some entry points are free to assume that
+ *  the call is not the first to the library and, thus, that this has
+ *  already been called.)
+ */
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram )
+{
+    if (pOpts == NULL) {
+        fputs( zAO_Bad, stderr );
+        exit( EXIT_FAILURE );
+    }
+
+    /*
+     *  IF the client has enabled translation and the translation procedure
+     *  is available, then go do it.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0)
+       && (pOpts->pTransProc != 0) ) {
+        (*pOpts->pTransProc)();
+        pOpts->fOptSet &= ~OPTPROC_TRANSLATE;
+    }
+
+    /*
+     *  IF the struct version is not the current, and also
+     *     either too large (?!) or too small,
+     *  THEN emit error message and fail-exit
+     */
+    if (  ( pOpts->structVersion  != OPTIONS_STRUCT_VERSION  )
+       && (  (pOpts->structVersion > OPTIONS_STRUCT_VERSION  )
+          || (pOpts->structVersion < OPTIONS_MINIMUM_VERSION )
+       )  )  {
+
+        fprintf( stderr, zAO_Err, pOpts->origArgVect[0],
+                 NUM_TO_VER( pOpts->structVersion ));
+        if (pOpts->structVersion > OPTIONS_STRUCT_VERSION )
+            fputs( zAO_Big, stderr );
+        else
+            fputs( zAO_Sml, stderr );
+
+        return FAILURE;
+    }
+
+    /*
+     *  If the program name hasn't been set, then set the name and the path
+     *  and the set of equivalent characters.
+     */
+    if (pOpts->pzProgName == NULL) {
+        const char* pz = strrchr( pzProgram, '/' );
+
+        if (pz == NULL)
+             pOpts->pzProgName = pzProgram;
+        else pOpts->pzProgName = pz+1;
+
+        pOpts->pzProgPath = pzProgram;
+
+        /*
+         *  when comparing long names, these are equivalent
+         */
+        strequate( zSepChars );
+    }
+
+    return SUCCESS;
+}
+
+
+/**
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/configfile.c */
diff --git a/sntp/libopts/cook.c b/sntp/libopts/cook.c
new file mode 100644 (file)
index 0000000..1cd2efd
--- /dev/null
@@ -0,0 +1,355 @@
+
+/*
+ *  $Id: cook.c,v 4.2 2005/06/07 22:26:44 bkorb Exp $
+ *  Time-stamp:      "2005-05-20 13:58:56 bkorb"
+ *
+ *  This file contains the routines that deal with processing quoted strings
+ *  into an internal format.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  ao_string_cook_escape_char
+ * private:
+ *
+ * what:  escape-process a string fragment
+ * arg:   + const char* + pzScan  + points to character after the escape +
+ * arg:   + char*       + pRes    + Where to put the result byte +
+ * arg:   + char        + nl_ch   + replacement char if scanned char is \n +
+ *
+ * ret-type: unsigned int
+ * ret-desc: The number of bytes consumed processing the escaped character.
+ *
+ * doc:
+ *
+ *  This function converts "t" into "\t" and all your other favorite
+ *  escapes, including numeric ones:  hex and ocatal, too.
+ *  The returned result tells the caller how far to advance the
+ *  scan pointer (passed in).  The default is to just pass through the
+ *  escaped character and advance the scan by one.
+ *
+ *  Some applications need to keep an escaped newline, others need to
+ *  suppress it.  This is accomplished by supplying a '\n' replacement
+ *  character that is different from \n, if need be.  For example, use
+ *  0x7F and never emit a 0x7F.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+unsigned int
+ao_string_cook_escape_char( const char* pzIn, char* pRes, char nl )
+{
+    unsigned int  res = 1;
+
+    switch (*pRes = *pzIn++) {
+    case NUL:         /* NUL - end of input string */
+        return 0;
+    case '\r':
+        if (*pzIn != '\n')
+            return 1;
+        res++;
+        /* FALLTHROUGH */
+    case '\n':        /* NL  - emit newline        */
+        *pRes = nl;
+        return res;
+
+    case 'a': *pRes = '\a'; break;
+    case 'b': *pRes = '\b'; break;
+    case 'f': *pRes = '\f'; break;
+    case 'n': *pRes = '\n'; break;
+    case 'r': *pRes = '\r'; break;
+    case 't': *pRes = '\t'; break;
+    case 'v': *pRes = '\v'; break;
+
+    case 'x':         /* HEX Escape       */
+        if (isxdigit( *pzIn ))  {
+            unsigned int  val;
+            unsigned char ch = *pzIn++;
+
+            if ((ch >= 'A') && (ch <= 'F'))
+                val = 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val = 10 + (ch - 'a');
+            else val = ch - '0';
+
+            ch = *pzIn;
+
+            if (! isxdigit( ch )) {
+                *pRes = val;
+                res   = 2;
+                break;
+            }
+            val <<= 4;
+            if ((ch >= 'A') && (ch <= 'F'))
+                val += 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val += 10 + (ch - 'a');
+            else val += ch - '0';
+
+            res = 3;
+            *pRes = val;
+        }
+        break;
+
+    default:
+        /*
+         *  IF the character copied was an octal digit,
+         *  THEN set the output character to an octal value
+         */
+        if (isdigit( *pRes ) && (*pRes < '8'))  {
+            unsigned int  val = *pRes - '0';
+            unsigned char ch  = *pzIn++;
+
+            /*
+             *  IF the second character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            val = (val<<3) + (ch - '0');
+            ch  = *pzIn;
+            res = 2;
+
+            /*
+             *  IF the THIRD character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            /*
+             *  IF the new value would not be too large,
+             *  THEN add on the third and last character value
+             */
+            if ((val<<3) < 0xFF) {
+                val = (val<<3) + (ch - '0');
+                res = 3;
+            }
+
+            *pRes = val;
+            break;
+        }
+    }
+
+    return res;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  A quoted string has been found.
+ *  Find the end of it and compress any escape sequences.
+ */
+/*=export_func  ao_string_cook
+ * private:
+ *
+ * what:  concatenate and escape-process strings
+ * arg:   + char* + pzScan     + The *MODIFIABLE* input buffer +
+ * arg:   + int*  + pLineCt    + The (possibly NULL) pointer to a line count +
+ *
+ * ret-type: char*
+ * ret-desc: The address of the text following the processed strings.
+ *           The return value is NULL if the strings are ill-formed.
+ *
+ * doc:
+ *
+ *  A series of one or more quoted strings are concatenated together.
+ *  If they are quoted with double quotes (@code{"}), then backslash
+ *  escapes are processed per the C programming language.  If they are
+ *  single quote strings, then the backslashes are honored only when they
+ *  precede another backslash or a single quote character.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+char*
+ao_string_cook( char* pzScan, int* pLineCt )
+{
+    int   l = 0;
+    char  q = *pzScan;
+
+    /*
+     *  It is a quoted string.  Process the escape sequence characters
+     *  (in the set "abfnrtv") and make sure we find a closing quote.
+     */
+    char* pzD = pzScan++;
+    char* pzS = pzScan;
+
+    if (pLineCt == NULL)
+        pLineCt = &l;
+
+    for (;;) {
+        /*
+         *  IF the next character is the quote character, THEN we may end the
+         *  string.  We end it unless the next non-blank character *after* the
+         *  string happens to also be a quote.  If it is, then we will change
+         *  our quote character to the new quote character and continue
+         *  condensing text.
+         */
+        while (*pzS == q) {
+            *pzD = NUL; /* This is probably the end of the line */
+            pzS++;
+
+        scan_for_quote:
+            while (isspace(*pzS))
+                if (*(pzS++) == '\n')
+                    (*pLineCt)++;
+
+            /*
+             *  IF the next character is a quote character,
+             *  THEN we will concatenate the strings.
+             */
+            switch (*pzS) {
+            case '"':
+            case '\'':
+                break;
+
+            case '/':
+                /*
+                 *  Allow for a comment embedded in the concatenated string.
+                 */
+                switch (pzS[1]) {
+                default:  return NULL;
+                case '/':
+                    /*
+                     *  Skip to end of line
+                     */
+                    pzS = strchr( pzS, '\n' );
+                    if (pzS == NULL)
+                        return NULL;
+                    (*pLineCt)++;
+                    break;
+
+                case '*':
+                {
+                    char* p = strstr( pzS+2, "*/" );
+                    /*
+                     *  Skip to terminating star slash
+                     */
+                    if (p == NULL)
+                        return NULL;
+                    while (pzS < p) {
+                        if (*(pzS++) == '\n')
+                            (*pLineCt)++;
+                    }
+
+                    pzS = p + 2;
+                }
+                }
+                goto scan_for_quote;
+
+            default:
+                /*
+                 *  The next non-whitespace character is not a quote.
+                 *  The series of quoted strings has come to an end.
+                 */
+                return pzS;
+            }
+
+            q = *(pzS++);  /* assign new quote character and advance scan */
+        }
+
+        /*
+         *  We are inside a quoted string.  Copy text.
+         */
+        switch (*(pzD++) = *(pzS++)) {
+        case NUL:
+            return NULL;
+
+        case '\n':
+            (*pLineCt)++;
+            break;
+
+        case '\\':
+            /*
+             *  IF we are escaping a new line,
+             *  THEN drop both the escape and the newline from
+             *       the result string.
+             */
+            if (*pzS == '\n') {
+                pzS++;
+                pzD--;
+                (*pLineCt)++;
+            }
+
+            /*
+             *  ELSE IF the quote character is '"' or '`',
+             *  THEN we do the full escape character processing
+             */
+            else if (q != '\'') {
+                int ct = ao_string_cook_escape_char( pzS, pzD-1, '\n' );
+                if (ct == 0)
+                    return NULL;
+
+                pzS += ct;
+            }     /* if (q != '\'')                  */
+
+            /*
+             *  OTHERWISE, we only process "\\", "\'" and "\#" sequences.
+             *  The latter only to easily hide preprocessing directives.
+             */
+            else switch (*pzS) {
+            case '\\':
+            case '\'':
+            case '#':
+                pzD[-1] = *pzS++;
+            }
+        }     /* switch (*(pzD++) = *(pzS++))    */
+    }         /* for (;;)                        */
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/cook.c */
diff --git a/sntp/libopts/enumeration.c b/sntp/libopts/enumeration.c
new file mode 100644 (file)
index 0000000..7f7a4b4
--- /dev/null
@@ -0,0 +1,449 @@
+
+/*
+ *  $Id: enumeration.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-14 14:29:55 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC*  pz_enum_err_fmt;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct );
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct )
+{
+    size_t max_len = 0;
+    size_t ttl_len = 0;
+
+    if (pOpts != NULL)
+        fprintf( option_usage_fp, pz_enum_err_fmt,
+                 pOpts->pzProgName, pOD->pzLastArg );
+
+    fprintf( option_usage_fp, zValidKeys, pOD->pz_Name );
+
+    if (**paz_names == 0x7F) {
+        paz_names++;
+        name_ct--;
+    }
+
+    /*
+     *  Figure out the maximum length of any name, plus the total length
+     *  of all the names.
+     */
+    {
+        tCC** paz = paz_names;
+        int   ct  = name_ct;
+
+        do  {
+            size_t len = strlen( *(paz++) ) + 1;
+            if (len > max_len)
+                max_len = len;
+            ttl_len += len;
+        } while (--ct > 0);
+    }
+
+    /*
+     *  IF any one entry is about 1/2 line or longer, print one per line
+     */
+    if (max_len > 35) {
+        do  {
+            fprintf( option_usage_fp, "  %s\n", *(paz_names++) );
+        } while (--name_ct > 0);
+    }
+
+    /*
+     *  ELSE IF they all fit on one line, then do so.
+     */
+    else if (ttl_len < 76) {
+        fputc( ' ', option_usage_fp );
+        do  {
+            fputc( ' ', option_usage_fp );
+            fputs( *(paz_names++), option_usage_fp );
+        } while (--name_ct > 0);
+        fputc( '\n', option_usage_fp );
+    }
+
+    /*
+     *  Otherwise, columnize the output
+     */
+    else {
+        int   ent_no = 0;
+        char  zFmt[16];  /* format for all-but-last entries on a line */
+
+        sprintf( zFmt, "%%-%ds", max_len );
+        max_len = 78 / max_len; /* max_len is now max entries on a line */
+        fputs( "  ", option_usage_fp );
+
+        /*
+         *  Loop through all but the last entry
+         */
+        while (--name_ct > 0) {
+            if (++ent_no == max_len) {
+                /*
+                 *  Last entry on a line.  Start next line, too.
+                 */
+                fprintf( option_usage_fp, "%s\n  ", *(paz_names++) );
+                ent_no = 0;
+            }
+
+            else
+                fprintf( option_usage_fp, zFmt, *(paz_names++) );
+        }
+        fprintf( option_usage_fp, "%s\n", *paz_names );
+    }
+
+    /*
+     *  IF we do not have a pOpts pointer, then this output is being requested
+     *  by the usage procedure.  Let's not re-invoke it recursively.
+     */
+    if (pOpts != NULL)
+        (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zSetMemberSettings, option_usage_fp );
+}
+
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    uintptr_t     res = name_ct;
+    size_t        len = strlen( (char*)pzName );
+    uintptr_t     idx;
+    /*
+     *  Look for an exact match, but remember any partial matches.
+     *  Multiple partial matches means we have an ambiguous match.
+     */
+    for (idx = 0; idx < name_ct; idx++) {
+        if (strncmp( (char*)paz_names[idx], (char*)pzName, len ) == 0) {
+            if (paz_names[idx][len] == NUL)
+                return idx;  /* full match */
+
+            if (res != name_ct) {
+                pz_enum_err_fmt = zAmbigKey;
+                option_usage_fp = stderr;
+                enumError( pOpts, pOD, paz_names, name_ct );
+            }
+            res = idx; /* save partial match */
+        }
+    }
+
+    /*
+     *  no partial match -> error
+     */
+    if (res == name_ct) {
+        pz_enum_err_fmt = zNoKey;
+        option_usage_fp = stderr;
+        enumError( pOpts, pOD, paz_names, name_ct );
+    }
+
+    /*
+     *  Return the matching index as a char* pointer.
+     *  The result gets stashed in a char* pointer, so it will have to fit.
+     */
+    return res;
+}
+
+
+/*=export_func  optionEnumerationVal
+ * what:  Convert between enumeration values and strings
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   tCC**,         paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * ret_type:  char*
+ * ret_desc:  the enumeration value cast as a char*
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+char*
+optionEnumerationVal(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return (char*)0UL;
+
+    case 1UL:
+        /*
+         *  print the name string.
+         */
+        fputs( paz_names[ (uintptr_t)(pOD->pzLastArg) ], stdout );
+        return (char*)0UL;
+
+    case 2UL:
+        /*
+         *  Replace the enumeration value with the name string.
+         */
+        return (char*)paz_names[ (uintptr_t)(pOD->pzLastArg) ];
+
+    default:
+        break;
+    }
+
+    return (char*)findName( pOD->pzLastArg, pOpts, pOD, paz_names, name_ct );
+}
+
+
+/*=export_func  optionSetMembers
+ * what:  Convert between bit flag values and strings
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   tCC**,         paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+void
+optionSetMembers(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return;
+
+    case 1UL:
+    {
+        /*
+         *  print the name string.
+         */
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        while (bits != 0) {
+            if (bits & 1) {
+                if (len++ > 0) fputs( " | ", stdout );
+                fputs( paz_names[ res ], stdout );
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    case 2UL:
+    {
+        char*     pz;
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        /*
+         *  Replace the enumeration value with the name string.
+         *  First, determine the needed length, then allocate and fill in.
+         */
+        while (bits != 0) {
+            if (bits & 1)
+                len += strlen( paz_names[ res ]) + 8;
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+
+        pOD->pzLastArg = pz = malloc( len );
+        /*
+         *  Start by clearing all the bits.  We want to turn off any defaults
+         *  because we will be restoring to current state, not adding to
+         *  the default set of bits.
+         */
+        strcpy( pz, "none" );
+        pz += 4;
+        bits = (uintptr_t)pOD->optCookie;
+        res = 0;
+        while (bits != 0) {
+            if (bits & 1) {
+                strcpy( pz, " + " );
+                strcpy( pz+3, paz_names[ res ]);
+                pz += strlen( paz_names[ res ]) + 3;
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    default:
+        break;
+    }
+
+    {
+        tCC*      pzArg = pOD->pzLastArg;
+        uintptr_t res;
+        if ((pzArg == NULL) || (*pzArg == NUL)) {
+            pOD->optCookie = (void*)0;
+            return;
+        }
+
+        res = (uintptr_t)pOD->optCookie;
+        for (;;) {
+            tSCC zSpn[] = " ,|+\t\r\f\n";
+            int  iv, len;
+
+            pzArg += strspn( pzArg, zSpn );
+            iv = (*pzArg == '!');
+            if (iv)
+                pzArg += strspn( pzArg+1, zSpn ) + 1;
+
+            len = strcspn( pzArg, zSpn );
+            if (len == 0)
+                break;
+
+            if ((len == 3) && (strncmp( pzArg, zAll, 3 ) == 0)) {
+                if (iv)
+                     res = 0;
+                else res = ~0;
+            }
+            else if ((len == 4) && (strncmp( pzArg, zNone, 4 ) == 0)) {
+                if (! iv)
+                    res = 0;
+            }
+            else do {
+                char* pz;
+                uintptr_t bit = strtoul( pzArg, &pz, 0 );
+
+                if (pz != pzArg + len) {
+                    char z[ AO_NAME_SIZE ];
+                    tCC* p;
+                    if (*pz != NUL) {
+                        if (len >= AO_NAME_LIMIT)
+                            break;
+                        strncpy( z, pzArg, len );
+                        z[len] = NUL;
+                        p = z;
+                    } else {
+                        p = pzArg;
+                    }
+
+                    bit = 1UL << findName(p, pOpts, pOD, paz_names, name_ct);
+                }
+                if (iv)
+                     res &= ~bit;
+                else res |= bit;
+            } while (0);
+
+            if (pzArg[len] == NUL)
+                break;
+            pzArg += len + 1;
+        }
+        if (name_ct < (8 * sizeof( uintptr_t ))) {
+            res &= (1UL << name_ct) - 1UL;
+        }
+
+        pOD->optCookie = (void*)res;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/enumeration.c */
diff --git a/sntp/libopts/environment.c b/sntp/libopts/environment.c
new file mode 100644 (file)
index 0000000..03079e6
--- /dev/null
@@ -0,0 +1,261 @@
+
+/*
+ *  $Id: environment.c,v 4.6 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-20 17:18:54 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  doPrognameEnv - check for preset values from the ${PROGNAME}
+ *  environment variable.  This is accomplished by parsing the text into
+ *  tokens, temporarily replacing the arg vector and calling
+ *  doImmediateOpts and/or doRegularOpts.
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
+{
+    const char*   pczOptStr = getenv( pOpts->pzPROGNAME );
+    token_list_t* pTL;
+    int           sv_argc;
+    tUI           sv_flag;
+    char**        sv_argv;
+
+    /*
+     *  IF there is no such environment variable
+     *   *or* there is, but we are doing immediate opts and there are
+     *        no immediate opts to do (--help inside $PROGNAME is silly,
+     *        but --no-load-defs is not, so that is marked)
+     *  THEN bail out now.  (
+     */
+    if (  (pczOptStr == NULL)
+       || (  (type == ENV_IMM)
+          && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0)  )  )
+        return;
+
+    /*
+     *  Tokenize the string.  If there's nothing of interest, we'll bail
+     *  here immediately.
+     */
+    pTL = ao_string_tokenize( pczOptStr );
+    if (pTL == NULL)
+        return;
+
+    /*
+     *  Substitute our $PROGNAME argument list for the real one
+     */
+    sv_argc = pOpts->origArgCt;
+    sv_argv = pOpts->origArgVect;
+    sv_flag = pOpts->fOptSet;
+
+    /*
+     *  We add a bogus pointer to the start of the list.  The program name
+     *  has already been pulled from "argv", so it won't get dereferenced.
+     *  The option scanning code will skip the "program name" at the start
+     *  of this list of tokens, so we accommodate this way ....
+     */
+    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
+    pOpts->origArgCt   = pTL->tkn_ct   + 1;
+    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
+
+    pOpts->curOptIdx   = 1;
+    pOpts->pzCurOpt    = NULL;
+
+    switch (type) {
+    case ENV_IMM:
+        /*
+         *  We know the OPTPROC_HAS_IMMED bit is set.
+         */
+        (void)doImmediateOpts( pOpts );
+        break;
+
+    case ENV_NON_IMM:
+        (void)doRegularOpts( pOpts );
+        break;
+
+    default:
+        /*
+         *  Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
+         */
+        if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
+            (void)doImmediateOpts( pOpts );
+            pOpts->curOptIdx = 1;
+            pOpts->pzCurOpt  = NULL;
+        }
+        (void)doRegularOpts( pOpts );
+        break;
+    }
+
+    /*
+     *  Free up the temporary arg vector and restore the original program args.
+     */
+    free( pTL );
+    pOpts->origArgVect = sv_argv;
+    pOpts->origArgCt   = sv_argc;
+    pOpts->fOptSet     = sv_flag;
+}
+
+
+/*
+ *  doEnvPresets - check for preset values from the envrionment
+ *  This routine should process in all, immediate or normal modes....
+ */
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type )
+{
+    int        ct;
+    tOptState  st;
+    char*      pzFlagName;
+    size_t     spaceLeft;
+    char       zEnvName[ AO_NAME_SIZE ];
+
+    /*
+     *  Finally, see if we are to look at the environment
+     *  variables for initial values.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
+        return;
+
+    doPrognameEnv( pOpts, type );
+
+    ct  = pOpts->presetOptCt;
+    st.pOD = pOpts->pOptDesc;
+
+    pzFlagName = zEnvName
+        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
+    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
+
+    for (;ct-- > 0; st.pOD++) {
+        /*
+         *  If presetting is disallowed, then skip this entry
+         */
+        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
+           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
+            continue;
+
+        /*
+         *  IF there is no such environment variable,
+         *  THEN skip this entry, too.
+         */
+        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
+            continue;
+
+        /*
+         *  Set up the option state
+         */
+        strcpy( pzFlagName, st.pOD->pz_NAME );
+        st.pzOptArg = getenv( zEnvName );
+        if (st.pzOptArg == NULL)
+            continue;
+        st.flags    = OPTST_PRESET | st.pOD->fOptState;
+        st.optType  = TOPT_UNDEFINED;
+
+        if (  (st.pOD->pz_DisablePfx != NULL)
+           && (streqvcmp( st.pzOptArg, st.pOD->pz_DisablePfx ) == 0)) {
+            st.flags |= OPTST_DISABLED;
+            st.pzOptArg = NULL;
+        }
+
+        switch (type) {
+        case ENV_IMM:
+            /*
+             *  Process only immediate actions
+             */
+            if (DO_IMMEDIATELY(st.flags))
+                break;
+            continue;
+
+        case ENV_NON_IMM:
+            /*
+             *  Process only NON immediate actions
+             */
+            if (DO_NORMALLY(st.flags) || DO_SECOND_TIME(st.flags))
+                break;
+            continue;
+
+        default: /* process everything */
+            break;
+        }
+
+        /*
+         *  Make sure the option value string is persistent and consistent.
+         *  This may be a memory leak, but we cannot do anything about it.
+         *
+         *  The interpretation of the option value depends
+         *  on the type of value argument the option takes
+         */
+        if (st.pzOptArg != NULL) {
+            if (OPTST_GET_ARGTYPE(st.pOD->fOptState) == OPARG_TYPE_NONE) {
+                st.pzOptArg = NULL;
+            } else if (  (st.pOD->fOptState & OPTST_ARG_OPTIONAL)
+                      && (*st.pzOptArg == NUL)) {
+                    st.pzOptArg = NULL;
+            } else if (*st.pzOptArg == NUL) {
+                st.pzOptArg = zNil;
+            } else {
+                AGDUPSTR( st.pzOptArg, st.pzOptArg, "option argument" );
+            }
+        }
+
+        handleOption( pOpts, &st );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/environment.c */
diff --git a/sntp/libopts/genshell.c b/sntp/libopts/genshell.c
new file mode 100644 (file)
index 0000000..7f695c9
--- /dev/null
@@ -0,0 +1,300 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.c)
+ *  
+ *  It has been AutoGen-ed  Thursday July 28, 2005 at 04:18:43 PM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "genshell.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "genshellopt copyright (c) 1999-2005 Bruce Korb, all rights reserved";
+tSCC zCopyrightNotice[] =
+       "genshellopt is free software; you can redistribute it and/or\n\
+modify it under the terms of the GNU Lesser General Public\n\
+License as published by the Free Software Foundation; either\n\
+version 2.1 of the License, or (at your option) any later version.\n\n\
+genshellopt is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n\
+Lesser General Public License for more details.\n\n\
+You should have received a copy of the GNU Lesser General Public\n\
+License along with genshellopt.  If not, write to:\n\
+\tThe Free Software Foundation, Inc.,\n\
+\t51 Franklin Street, Fifth Floor\n\
+\tBoston, MA  02110-1301, USA.";
+extern tUsageProc genshelloptUsage;
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Script option description:
+ */
+tSCC    zScriptText[] =
+        "Output Script File";
+tSCC    zScript_NAME[]             = "SCRIPT";
+tSCC    zScript_Name[]             = "script";
+#define SCRIPT_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Shell option description:
+ */
+tSCC    zShellText[] =
+        "Shell name (follows \"#!\" magic)";
+tSCC    zShell_NAME[]              = "SHELL";
+tSCC    zNotShell_Name[]           = "no-shell";
+tSCC    zNotShell_Pfx[]            = "no";
+#define zShell_Name                  (zNotShell_Name + 3)
+#define SHELL_FLAGS       (OPTST_INITENABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+/*
+ *  Declare option callback procedures
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doUsageOpt;
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equiv idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SCRIPT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zScriptText, zScript_NAME, zScript_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_SHELL,
+     /* equiv idx, value */ 1, VALUE_OPT_SHELL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SHELL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zShellText, zShell_NAME, zShell_Name,
+     /* disablement strs */ zNotShell_Name, zNotShell_Pfx },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionPrintVersion,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Environment
+ */
+tSCC   zPROGNAME[]   = "GENSHELLOPT";
+tSCC   zUsageTitle[] =
+"genshellopt - Generate Shell Option Processing Script - Ver. 1\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+#define zRcName     NULL
+#define apzHomeList NULL
+
+tSCC   zBugsAddr[]    = "autogen-users@lists.sf.net";
+tSCC   zExplain[]     = "\n\
+Note that `shell' is only useful if the output file does not already\n\
+exist.  If it does, then the shell name and optional first argument\n\
+will be extracted from the script file.\n";
+tSCC    zDetail[]     = "\n\
+If the script file already exists and contains Automated Option Processing\n\
+text, the second line of the file through the ending tag will be replaced\n\
+by the newly generated text.  The first `#!' line will be regenerated.\n";
+tSCC    zFullVersion[] = GENSHELLOPT_FULL_VERSION;
+/* extracted from optcode.tpl near line 309 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions genshelloptOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_NEGATIONS
+    + OPTPROC_NO_ARGS ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    genshelloptUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+       0 /* no option state saving */,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 2 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+/* extracted from optcode.tpl near line 396 */
+
+#if ENABLE_NLS
+#include <string.h>
+#include <stdio.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = genshelloptOptions.pOptDesc;
+        int       ix  = genshelloptOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    genshelloptOptions.pzCopyright   = AO_gettext(genshelloptOptions.pzCopyright);
+    genshelloptOptions.pzCopyNotice  = AO_gettext(genshelloptOptions.pzCopyNotice);
+    genshelloptOptions.pzFullVersion = AO_gettext(genshelloptOptions.pzFullVersion);
+    genshelloptOptions.pzUsageTitle  = AO_gettext(genshelloptOptions.pzUsageTitle);
+    genshelloptOptions.pzExplain     = AO_gettext(genshelloptOptions.pzExplain);
+    genshelloptOptions.pzDetail      = AO_gettext(genshelloptOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/sntp/libopts/genshell.h b/sntp/libopts/genshell.h
new file mode 100644 (file)
index 0000000..a2a17c1
--- /dev/null
@@ -0,0 +1,143 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.h)
+ *  
+ *  It has been AutoGen-ed  Thursday July 28, 2005 at 04:18:43 PM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the genshellopt program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_GENSHELL_H_GUARD
+#define AUTOOPTS_GENSHELL_H_GUARD
+
+/*
+ * genshellopt copyright 1999-2005 Bruce Korb - all rights reserved
+ *
+ * genshellopt is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * genshellopt 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with genshellopt.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 102400
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_SCRIPT           =  0,
+        INDEX_OPT_SHELL            =  1,
+        INDEX_OPT_VERSION          = 2,
+        INDEX_OPT_HELP             = 3,
+        INDEX_OPT_MORE_HELP        = 4
+} teOptIndex;
+
+#define OPTION_CT    5
+#define GENSHELLOPT_VERSION       "1"
+#define GENSHELLOPT_FULL_VERSION  "genshellopt - Generate Shell Option Processing Script - Ver. 1"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( SCRIPT )
+ */
+#define         DESC(n) genshelloptOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_SCRIPT         'o'
+#define VALUE_OPT_SHELL          's'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( genshelloptOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( genshelloptOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                genshelloptOptions.curOptIdx = (n); \
+                genshelloptOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*genshelloptOptions.pUsageProc)( &genshelloptOptions, c )
+/* extracted from opthead.tpl near line 260 */
+
+/* * * * * *
+ *
+ *  Declare the genshellopt option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   genshelloptOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_GENSHELL_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/sntp/libopts/libopts.c b/sntp/libopts/libopts.c
new file mode 100644 (file)
index 0000000..e39dbbc
--- /dev/null
@@ -0,0 +1,29 @@
+#define AUTOOPTS_INTERNAL
+#include "config.h"
+#include "autoopts/options.h"
+#include "autoopts/usage-txt.h"
+#include "genshell.h"
+#include "autoopts.h"
+#include "proto.h"
+#include "autoopts.c"
+#include "boolean.c"
+#include "configfile.c"
+#include "cook.c"
+#include "enumeration.c"
+#include "environment.c"
+#include "genshell.c"
+#include "load.c"
+#include "makeshell.c"
+#include "nested.c"
+#include "numeric.c"
+#include "pgusage.c"
+#include "putshell.c"
+#include "restore.c"
+#include "save.c"
+#include "sort.c"
+#include "stack.c"
+#include "streqvcmp.c"
+#include "text_mmap.c"
+#include "tokenize.c"
+#include "usage.c"
+#include "version.c"
diff --git a/sntp/libopts/libopts.m4 b/sntp/libopts/libopts.m4
new file mode 100644 (file)
index 0000000..c48cd1d
--- /dev/null
@@ -0,0 +1,418 @@
+dnl  -*- buffer-read-only: t -*- vi: set ro:
+dnl 
+dnl DO NOT EDIT THIS FILE   (libopts.m4)
+dnl 
+dnl It has been AutoGen-ed  Thursday July 28, 2005 at 04:18:42 PM PDT
+dnl From the definitions    libopts.def
+dnl and the template file   conftest.tpl
+dnl
+dnl @synopsis  INVOKE_LIBOPTS_MACROS
+dnl
+dnl  This macro will invoke the AutoConf macros specified in libopts.def
+dnl  that have not been disabled with "omit-invocation".
+dnl
+AC_DEFUN([LIBOPTS_WITH_REGEX_HEADER],[
+  AC_ARG_WITH([regex-header],
+    AC_HELP_STRING([--with-regex-header], [a reg expr header is specified]),
+    [libopts_cv_with_regex_header=${with_regex_header}],
+    AC_CACHE_CHECK([whether a reg expr header is specified], libopts_cv_with_regex_header,
+      libopts_cv_with_regex_header=no)
+  ) # end of AC_ARG_WITH
+
+  if test "X${libopts_cv_with_regex_header}" != Xno
+  then
+    AC_DEFINE_UNQUOTED([REGEX_HEADER],[<${libopts_cv_with_regex_header}>])
+  else
+    AC_DEFINE([REGEX_HEADER],[<regex.h>],[name of regex header file])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITH_REGEX_HEADER
+
+
+AC_DEFUN([LIBOPTS_WITHLIB_REGEX],[
+  AC_ARG_WITH([libregex],
+    AC_HELP_STRING([--with-libregex], [libregex installation prefix]),
+    [libopts_cv_with_libregex_root=${with_libregex}],
+    AC_CACHE_CHECK([whether with-libregex was specified], libopts_cv_with_libregex_root,
+      libopts_cv_with_libregex_root=no)
+  ) # end of AC_ARG_WITH libregex
+
+  if test "${with_libguile+set}" = set && \
+     test "${withval}" = no
+  then ## disabled by request
+    libopts_cv_with_libregex_root=no
+    libopts_cv_with_libregex_cflags=no
+    libopts_cv_with_libregex_libs=no
+  else
+
+  AC_ARG_WITH([libregex-cflags],
+    AC_HELP_STRING([--with-libregex-cflags], [libregex compile flags]),
+    [libopts_cv_with_libregex_cflags=${with_regex_cflags}],
+    AC_CACHE_CHECK([whether with-libregex-cflags was specified], libopts_cv_with_libregex_cflags,
+      libopts_cv_with_libregex_cflags=no)
+  ) # end of AC_ARG_WITH libregex-cflags
+
+  AC_ARG_WITH([libregex-libs],
+    AC_HELP_STRING([--with-libregex-libs], [libregex link command arguments]),
+    [libopts_cv_with_libregex_libs=${with_regex_libs}],
+    AC_CACHE_CHECK([whether with-libregex-libs was specified], libopts_cv_with_libregex_libs,
+      libopts_cv_with_libregex_libs=no)
+  ) # end of AC_ARG_WITH libregex-libs
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_cflags=no ;;
+    * )        libopts_cv_with_libregex_cflags=-I${libopts_cv_with_libregex_root}/include ;;
+    esac
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_libs=no ;;
+    * )        libopts_cv_with_libregex_libs="-L${libopts_cv_with_libregex_root}/lib -lregex";;
+    esac
+  esac
+  libopts_save_CPPFLAGS="${CPPFLAGS}"
+  libopts_save_LIBS="${LIBS}"
+  fi ## disabled by request
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_cflags="" ;;
+  * ) CPPFLAGS="${CPPFLAGS} ${libopts_cv_with_libregex_cflags}" ;;
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_libs="" ;;
+  * )
+    LIBS="${LIBS} ${libopts_cv_with_libregex_libs}" ;;
+  esac
+  LIBREGEX_CFLAGS=""
+  LIBREGEX_LIBS=""
+  AC_MSG_CHECKING([whether libregex functions properly])
+  AC_CACHE_VAL([libopts_cv_with_libregex],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+@%:@include <stdlib.h>
+@%:@include <sys/types.h>
+@%:@include REGEX_HEADER
+static regex_t re;
+void comp_re( const char* pzPat ) {
+  int res = regcomp( &re, pzPat, REG_EXTENDED|REG_ICASE|REG_NEWLINE );
+  if (res == 0) return;
+  exit( res ); }
+int main() {
+  regmatch_t m@<:@2@:>@;
+  comp_re( "^.*\@S|@"   );
+  comp_re( "()|no.*" );
+  comp_re( "."       );
+  if (regexec( &re, "X", 2, m, 0 ) != 0)  return 1;
+  if ((m@<:@0@:>@.rm_so != 0) || (m@<:@0@:>@.rm_eo != 1)) {
+    fputs( "error: regex -->.<-- did not match\n", stderr );
+    return 1;
+  }
+  return 0; }],
+    [libopts_cv_with_libregex=yes], [libopts_cv_with_libregex=no],
+    [libopts_cv_with_libregex=no]) # end of AC_TRY_RUN 
+  ]) # end of AC_CACHE_VAL for libopts_cv_with_libregex
+  AC_MSG_RESULT([${libopts_cv_with_libregex}])
+
+  if test "X${libopts_cv_with_libregex}" = Xno
+  then
+    CPPFLAGS="${libopts_save_CPPFLAGS}"
+    LIBS="${libopts_save_LIBS}"
+               cat >&2 <<'_EOF_'
+I cannot detect POSIX compliant regcomp/regexec routines.
+These are required for AutoGen to work correctly.  If you have
+such a library present on your system, you must specify it by
+setting the LIBS environment variable, e.g., "LIBS='-lregex'".
+If you do not have such a library on your system, then you should
+download and install, for example, the one from:
+    ftp://ftp.gnu.org/gnu/rx/
+_EOF_
+AC_MSG_ERROR([Cannot find working POSIX regex library])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITHLIB_REGEX
+
+
+AC_DEFUN([LIBOPTS_RUN_PATHFIND],[
+  AC_MSG_CHECKING([whether pathfind(3) works])
+  AC_CACHE_VAL([libopts_cv_run_pathfind],[
+  AC_TRY_RUN([@%:@include <string.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+   char* pz = pathfind( getenv( "PATH" ), "sh", "x" );
+   return (pz == 0) ? 1 : 0;
+}],
+    [libopts_cv_run_pathfind=yes],[libopts_cv_run_pathfind=no],[libopts_cv_run_pathfind=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_pathfind
+  AC_MSG_RESULT([${libopts_cv_run_pathfind}])
+
+  if test "X${libopts_cv_run_pathfind}" != Xno
+  then
+    AC_DEFINE([HAVE_PATHFIND],[1],
+        [Define this if pathfind(3) works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_PATHFIND
+
+
+AC_DEFUN([LIBOPTS_RUN_REALPATH],[
+  AC_MSG_CHECKING([whether we have a functional realpath(3C)])
+  AC_CACHE_VAL([libopts_cv_run_realpath],[
+  AC_TRY_RUN([@%:@include <limits.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+@%:@ifndef PATH_MAX
+choke me!!
+@%:@else
+   char zPath@<:@PATH_MAX+1@:>@;
+@%:@endif
+   char *pz = realpath(argv@<:@0@:>@, zPath);
+   return (pz == zPath) ? 0 : 1;
+}],
+    [libopts_cv_run_realpath=yes],[libopts_cv_run_realpath=no],[libopts_cv_run_realpath=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_realpath
+  AC_MSG_RESULT([${libopts_cv_run_realpath}])
+
+  if test "X${libopts_cv_run_realpath}" != Xno
+  then
+    AC_DEFINE([HAVE_REALPATH],[1],
+        [Define this if we have a functional realpath(3C)])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_REALPATH
+
+
+AC_DEFUN([LIBOPTS_RUN_STRFTIME],[
+  AC_MSG_CHECKING([whether strftime() works])
+  AC_CACHE_VAL([libopts_cv_run_strftime],[
+  AC_TRY_RUN([@%:@include <time.h>
+@%:@include <string.h>
+char t_buf@<:@ 64 @:>@;
+int main() {
+  static const char z@<:@@:>@ = "Thursday Aug 28 240";
+  struct tm tm;
+  tm.tm_sec   = 36;  /* seconds after the minute @<:@0, 61@:>@  */
+  tm.tm_min   = 44;  /* minutes after the hour @<:@0, 59@:>@ */
+  tm.tm_hour  = 12;  /* hour since midnight @<:@0, 23@:>@ */
+  tm.tm_mday  = 28;  /* day of the month @<:@1, 31@:>@ */
+  tm.tm_mon   =  7;  /* months since January @<:@0, 11@:>@ */
+  tm.tm_year  = 86;  /* years since 1900 */
+  tm.tm_wday  =  4;  /* days since Sunday @<:@0, 6@:>@ */
+  tm.tm_yday  = 239; /* days since January 1 @<:@0, 365@:>@ */
+  tm.tm_isdst =  1;  /* flag for daylight savings time */
+  strftime( t_buf, sizeof( t_buf ), "%A %b %d %j", &tm );
+  return (strcmp( t_buf, z ) != 0); }],
+    [libopts_cv_run_strftime=yes],[libopts_cv_run_strftime=no],[libopts_cv_run_strftime=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_strftime
+  AC_MSG_RESULT([${libopts_cv_run_strftime}])
+
+  if test "X${libopts_cv_run_strftime}" != Xno
+  then
+    AC_DEFINE([HAVE_STRFTIME],[1],
+        [Define this if strftime() works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_STRFTIME
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_BINARY],[
+  AC_MSG_CHECKING([whether fopen accepts "b" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_binary],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rb");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_binary=yes],[libopts_cv_run_fopen_binary=no],[libopts_cv_run_fopen_binary=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_binary
+  AC_MSG_RESULT([${libopts_cv_run_fopen_binary}])
+
+  if test "X${libopts_cv_run_fopen_binary}" != Xno
+  then
+    AC_DEFINE([FOPEN_BINARY_FLAG],"b",
+       [fopen(3) accepts a 'b' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_BINARY_FLAG],"",
+       [fopen(3) accepts a 'b' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_BINARY
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_TEXT],[
+  AC_MSG_CHECKING([whether fopen accepts "t" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_text],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rt");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_text=yes],[libopts_cv_run_fopen_text=no],[libopts_cv_run_fopen_text=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_text
+  AC_MSG_RESULT([${libopts_cv_run_fopen_text}])
+
+  if test "X${libopts_cv_run_fopen_text}" != Xno
+  then
+    AC_DEFINE([FOPEN_TEXT_FLAG],"t",
+       [fopen(3) accepts a 't' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_TEXT_FLAG],"",
+       [fopen(3) accepts a 't' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_TEXT
+
+
+AC_DEFUN([INVOKE_LIBOPTS_MACROS],[
+  # Check to see if a reg expr header is specified.
+  LIBOPTS_WITH_REGEX_HEADER
+
+  # Check to see if a working libregex can be found.
+  LIBOPTS_WITHLIB_REGEX
+
+  # Check to see if pathfind(3) works.
+  LIBOPTS_RUN_PATHFIND
+
+  # Check to see if we have a functional realpath(3C).
+  LIBOPTS_RUN_REALPATH
+
+  # Check to see if strftime() works.
+  LIBOPTS_RUN_STRFTIME
+
+  # Check to see if fopen accepts "b" mode.
+  LIBOPTS_RUN_FOPEN_BINARY
+
+  # Check to see if fopen accepts "t" mode.
+  LIBOPTS_RUN_FOPEN_TEXT
+  
+  # ----------------------------------------------------------------------
+  # Check for standard headers.
+  # ----------------------------------------------------------------------
+  # =================
+  # AC_HEADER_STDC
+  # =================
+  AC_HEADER_STDC
+  # =================
+  # AC_HEADER_DIRENT
+  # =================
+  AC_HEADER_DIRENT
+  
+  # ----------------------------------------------------------------------
+  # AC_CHECK_HEADERS Check for list of headers.
+  # ----------------------------------------------------------------------
+  AC_CHECK_HEADERS(dlfcn.h errno.h fcntl.h libgen.h memory.h netinet/in.h \
+    setjmp.h sys/mman.h sys/param.h sys/poll.h sys/procset.h sys/select.h \
+    sys/socket.h sys/stropts.h sys/time.h sys/un.h sys/wait.h unistd.h)
+  
+  # --------------------------------------------
+  # Verify certain entries from AC_CHECK_HEADERS
+  # --------------------------------------------
+  for f in sys_types sys_mman sys_param sys_stat sys_wait \
+           string errno stdlib memory setjmp
+  do eval as_ac_var=\${ac_cv_header_${f}_h+set}
+     test "${as_ac_var}" = set || \
+       AC_MSG_ERROR([You must have ${f}.h on your system])
+  done
+  
+  # =================
+  # AC_CHECK_HEADERS: stdarg.h is present define HAVE_STDARG_H, otherwise
+  # if varargs.h is present define HAVE_VARARGS_H.
+  # =================
+  AC_CHECK_HEADERS(stdarg.h varargs.h, break)
+  if test `eval echo '${'$as_ac_Header'}'` != yes; then
+    AC_MSG_ERROR([You must have stdarg.h or varargs.h on your system])
+  fi
+  
+  # =================
+  # Similarly for the string.h and strings.h headers
+  # =================
+  AC_CHECK_HEADERS(string.h strings.h, break)
+  if test `eval echo '${'$as_ac_Header'}'` != yes; then
+    AC_MSG_ERROR([You must have string.h or strings.h on your system])
+  fi
+  
+  # =================
+  # ...and limits headers
+  # =================
+  AC_CHECK_HEADERS(limits.h sys/limits.h values.h, break)
+  if test `eval echo '${'$as_ac_Header'}'` != yes; then
+    AC_MSG_ERROR([You must have one of limits.h, sys/limits.h or values.h])
+  fi
+  
+  # =================
+  # ...and int types headers
+  # =================
+  AC_CHECK_HEADERS(stdint.h inttypes.h, break)
+  if test `eval echo '${'$as_ac_Header'}'` != yes; then
+    AC_MSG_ERROR([You must have stdint.h or inttypes.h on your system])
+  fi
+  
+  # ----------------------------------------------------------------------
+  # AC_CHECK_LIB for SVR4 libgen, and use it if it defines pathfind.
+  # ----------------------------------------------------------------------
+  AC_CHECK_LIB(gen, pathfind)
+  AC_CHECK_FUNCS(mmap canonicalize_file_name)
+]) # end AC_DEFUN of INVOKE_LIBOPTS_MACROS
+
+dnl @synopsis  LIBOPTS_CHECK
+dnl
+dnl If autoopts-config works, add the linking information to LIBS.
+dnl Otherwise, add \`\`libopts-${ao_rev}''
+dnl to SUBDIRS and run all the config tests that the library needs.
+dnl
+dnl Default to system libopts
+NEED_LIBOPTS_DIR=''
+
+AC_DEFUN([LIBOPTS_CHECK],[
+  AC_ARG_ENABLE([local-libopts],
+    AC_HELP_STRING([--enable-local-libopts],
+       [Force using the supplied libopts tearoff code]),[
+    if test x$enableval = xyes ; then
+       AC_MSG_NOTICE([Using supplied libopts tearoff])
+       LIBOPTS_LDADD='$(top_builddir)/libopts/libopts.la'
+       LIBOPTS_CFLAGS='-I$(top_srcdir)/libopts'
+       INVOKE_LIBOPTS_MACROS
+       NEED_LIBOPTS_DIR=true
+    fi])
+
+  if test -z "${NEED_LIBOPTS_DIR}" ; then
+    AC_MSG_CHECKING([whether autoopts-config can be found])
+    AC_ARG_WITH([autoopts-config],
+       AC_HELP_STRING([--with-autoopts-config],
+            [specify the config-info script]),
+       [lo_cv_with_autoopts_config=${with_autoopts_config}],
+       AC_CACHE_CHECK([whether autoopts-config is specified],
+            lo_cv_with_autoopts_config,
+            lo_cv_with_autoopts_config=autoopts-config)
+     ) # end of AC_ARG_WITH
+     AC_CACHE_VAL([lo_cv_test_autoopts],[
+         aoconfig=${lo_cv_with_autoopts_config}
+         lo_cv_test_autoopts=`${aoconfig} --libs` 2> /dev/null
+         if test $? -ne 0 -o -z "${lo_cv_test_autoopts}"
+        then lo_cv_test_autoopts=no ; fi
+    ]) # end of CACHE_VAL
+    AC_MSG_RESULT([${lo_cv_test_autoopts}])
+
+    if test "X${lo_cv_test_autoopts}" != Xno
+    then
+      LIBOPTS_LDADD="${lo_cv_test_autoopts}"
+      LIBOPTS_CFLAGS="`${aoconfig} --cflags`"
+    else
+      LIBOPTS_LDADD='$(top_builddir)/libopts/libopts.la'
+      LIBOPTS_CFLAGS='-I$(top_srcdir)/libopts'
+      INVOKE_LIBOPTS_MACROS
+      NEED_LIBOPTS_DIR=true
+    fi
+  fi # end of if test -z "${NEED_LIBOPTS_DIR}"
+
+  AM_CONDITIONAL([NEED_LIBOPTS], [test -n "${NEED_LIBOPTS_DIR}"])
+  AC_SUBST(LIBOPTS_LDADD)
+  AC_SUBST(LIBOPTS_CFLAGS)
+  AC_CONFIG_FILES([libopts/Makefile])
+]) # end of AC_DEFUN of LIBOPTS_CHECK
diff --git a/sntp/libopts/load.c b/sntp/libopts/load.c
new file mode 100644 (file)
index 0000000..58f245b
--- /dev/null
@@ -0,0 +1,516 @@
+
+/*
+ *  $Id: load.c,v 4.15 2005/07/27 19:59:19 bkorb Exp $
+ *  Time-stamp:      "2005-07-26 10:39:46 bkorb"
+ *
+ *  This file contains the routines that deal with processing text strings
+ *  for options, either from a NUL-terminated string passed in or from an
+ *  rc/ini file.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionMakePath
+ * private:
+ *
+ * what:  translate and construct a path
+ * arg:   + char* + pzBuf      + The result buffer +
+ * arg:   + int   + bufSize    + The size of this buffer +
+ * arg:   + tCC*  + pzName     + The input name +
+ * arg:   + tCC*  + pzProgPath + The full path of the current program +
+ *
+ * ret-type: ag_bool
+ * ret-desc: AG_TRUE if the name was handled, otherwise AG_FALSE.
+ *           If the name does not start with ``$'', then it is handled
+ *           simply by copying the input name to the output buffer.
+ *
+ * doc:
+ *
+ *  This routine will copy the @code{pzName} input name into the @code{pzBuf}
+ *  output buffer, carefully not exceeding @code{bufSize} bytes.  If the
+ *  first character of the input name is a @code{'$'} character, then there
+ *  is special handling:
+ *  @*
+ *  @code{$$} is replaced with the directory name of the @code{pzProgPath},
+ *  searching @code{$PATH} if necessary.
+ *  @*
+ *  @code{$NAME} is replaced by the contents of the @code{NAME} environment
+ *  variable.
+ *
+ *  Please note: both @code{$$} and @code{$NAME} must be at the start of the
+ *     @code{pzName} string and must either be the entire string or be followed
+ *     by the @code{'/'} character.
+ *
+ * err:  @code{AG_FALSE} is returned if:
+ *       @*
+ *       @bullet{} @code{$$} is not the full string and
+ *                 the next character is not '/'.
+ *       @*
+ *       @bullet{} @code{$NAME} is not the full string and
+ *                 the next character is not '/'.
+ *       @*
+ *       @bullet{} @code{NAME} is not a known environment variable
+=*/
+ag_bool
+optionMakePath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    ag_bool res = AG_TRUE;
+
+    if (bufSize <= strlen( pzName ))
+        return AG_FALSE;
+
+    /*
+     *  IF not an environment variable, just copy the data
+     */
+    if (*pzName != '$') {
+        char* pzS = pzName;
+        char* pzD = pzBuf;
+        int   ct  = bufSize;
+
+        for (;;) {
+            if ( (*(pzD++) = *(pzS++)) == NUL)
+                break;
+            if (--ct == 0)
+                return AG_FALSE;
+        }
+    }
+
+    /*
+     *  IF the name starts with "$$", then it must be "$$" or
+     *  it must start with "$$/".  In either event, replace the "$$"
+     *  with the path to the executable and append a "/" character.
+     */
+    else if (pzName[1] == '$')
+        res = insertProgramPath( pzBuf, bufSize, pzName, pzProgPath );
+    else
+        res = insertEnvVal( pzBuf, bufSize, pzName, pzProgPath );
+
+    if (! res)
+        return AG_FALSE;
+
+#if defined(HAVE_CANONICALIZE_FILE_NAME)
+    do {
+        char* pz = canonicalize_file_name(pzBuf);
+        if (pz == NULL)
+            return AG_FALSE;
+        if (strlen(pz) < bufSize)
+            strcpy(pzBuf, pz);
+        free(pz);
+    } while (0);
+
+#elif defined(HAVE_REALPATH)
+    {
+        char z[ PATH_MAX+1 ];
+
+        if (realpath( pzBuf, z ) == NULL)
+            return AG_FALSE;
+
+        if (strlen(z) < bufSize)
+            strcpy( pzBuf, z );
+    }
+#endif
+
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    tCC*    pzPath;
+    tCC*    pz;
+    int     skip = 2;
+
+    switch (pzName[2]) {
+    case '/':
+        skip = 3;
+    case NUL:
+        break;
+    default:
+        return AG_FALSE;
+    }
+
+    /*
+     *  See if the path is included in the program name.
+     *  If it is, we're done.  Otherwise, we have to hunt
+     *  for the program using "pathfind".
+     */
+    if (strchr( pzProgPath, '/' ) != NULL)
+        pzPath = pzProgPath;
+    else {
+        pzPath = pathfind( getenv( "PATH" ), (char*)pzProgPath, "rx" );
+
+        if (pzPath == NULL)
+            return AG_FALSE;
+    }
+
+    pz = strrchr( pzPath, '/' );
+
+    /*
+     *  IF we cannot find a directory name separator,
+     *  THEN we do not have a path name to our executable file.
+     */
+    if (pz == NULL)
+        return AG_FALSE;
+
+    pzName += skip;
+
+    /*
+     *  Concatenate the file name to the end of the executable path.
+     *  The result may be either a file or a directory.
+     */
+    if ((pz - pzPath)+1 + strlen(pzName) >= bufSize)
+        return AG_FALSE;
+
+    memcpy( pzBuf, pzPath, (pz - pzPath)+1 );
+    strcpy( pzBuf + (pz - pzPath) + 1, pzName );
+
+    /*
+     *  If the "pzPath" path was gotten from "pathfind()", then it was
+     *  allocated and we need to deallocate it.
+     */
+    if (pzPath != pzProgPath)
+        free( (void*)pzPath );
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    char* pzDir = pzBuf;
+
+    for (;;) {
+        char ch = *++pzName;
+        if (! ISNAMECHAR( ch ))
+            break;
+        *(pzDir++) = ch;
+    }
+
+    if (pzDir == pzBuf)
+        return AG_FALSE;
+
+    *pzDir = NUL;
+
+    pzDir = getenv( pzBuf );
+
+    /*
+     *  Environment value not found -- skip the home list entry
+     */
+    if (pzDir == NULL)
+        return AG_FALSE;
+
+    if (strlen( pzDir ) + 1 + strlen( pzName ) >= bufSize)
+        return AG_FALSE;
+
+    sprintf( pzBuf, "%s%s", pzDir, pzName );
+    return AG_TRUE;
+}
+
+
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode )
+{
+    char* pzE;
+
+    if (mode == OPTION_LOAD_KEEP)
+        return;
+
+    if (isspace( *pzTxt )) {
+        char* pzS = pzTxt;
+        char* pzD = pzTxt;
+        while (isspace( *++pzS ))  ;
+        while ((*(pzD++) = *(pzS++)) != NUL)   ;
+        pzE = pzD-1;
+    } else
+        pzE = pzTxt + strlen( pzTxt );
+
+    while ((pzE > pzTxt) && isspace( pzE[-1] ))  pzE--;
+    *pzE = NUL;
+
+    if (mode == OPTION_LOAD_UNCOOKED)
+        return;
+
+    switch (*pzTxt) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    switch (pzE[-1]) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    (void)ao_string_cook( pzTxt, NULL );
+}
+
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode )
+{
+    tSCC zBrk[] = " \t:=";
+    char* pzEnd = strpbrk( pzTxt, zBrk );
+    int   space_break;
+
+    /*
+     *  Not having an argument to a configurable name is okay.
+     */
+    if (pzEnd == NULL)
+        return pzTxt + strlen(pzTxt);
+
+    /*
+     *  If we are keeping all whitespace, then the value starts with the
+     *  character that follows the end of the configurable name, regardless
+     *  of which character caused it.
+     */
+    if (mode == OPTION_LOAD_KEEP) {
+        *(pzEnd++) = NUL;
+        return pzEnd;
+    }
+
+    /*
+     *  If the name ended on a white space character, remember that
+     *  because we'll have to skip over an immediately following ':' or '='
+     *  (and the white space following *that*).
+     */
+    space_break = isspace(*pzEnd);
+    *(pzEnd++) = NUL;
+    while (isspace(*pzEnd))  pzEnd++;
+    if (space_break && ((*pzEnd == ':') || (*pzEnd == '=')))
+        pzEnd++;
+
+    mungeString( pzEnd, mode );
+    return pzEnd;
+}
+
+
+/*
+ *  Load an option from a block of text.  The text must start with the
+ *  configurable/option name and be followed by its associated value.
+ *  That value may be processed in any of several ways.  See "tOptionLoadMode"
+ *  in autoopts.h.
+ */
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode )
+{
+    while (isspace( *pzLine ))  pzLine++;
+
+    {
+        char* pzArg = assembleArgValue( pzLine, load_mode );
+
+        if (! SUCCESSFUL( longOptionFind( pOpts, pzLine, pOS )))
+            return;
+        if (pOS->flags & OPTST_NO_INIT)
+            return;
+        pOS->pzOptArg = pzArg;
+    }
+
+    switch (pOS->flags & (OPTST_IMM|OPTST_DISABLE_IMM)) {
+    case 0:
+        /*
+         *  The selected option has no immediate action.
+         *  THEREFORE, if the direction is PRESETTING
+         *  THEN we skip this option.
+         */
+        if (PRESETTING(direction))
+            return;
+        break;
+
+    case OPTST_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        }
+        break;
+
+    case OPTST_DISABLE_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        }
+        break;
+
+    case OPTST_IMM|OPTST_DISABLE_IMM:
+        /*
+         *  The selected option is always for immediate action.
+         *  THEREFORE, if the direction is PROCESSING
+         *  THEN we skip this option.
+         */
+        if (PROCESSING(direction))
+            return;
+        break;
+    }
+
+    /*
+     *  Fix up the args.
+     */
+    if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+        if (*pOS->pzOptArg != NUL)
+            return;
+        pOS->pzOptArg = NULL;
+
+    } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = NULL;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+
+    } else {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = zNil;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+    }
+
+    handleOption( pOpts, pOS );
+}
+
+
+/*=export_func  optionLoadLine
+ *
+ * what:  process a string for an option name and value
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ * arg:   const char*, pzLine, NUL-terminated text
+ *
+ * doc:
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ *
+ * err:   Invalid options are silently ignored.  Invalid option arguments
+ *        will cause a warning to print, but the function should return.
+=*/
+void
+optionLoadLine(
+    tOptions*  pOpts,
+    tCC*       pzLine )
+{
+    tOptState st = OPTSTATE_INITIALIZER(SET);
+    char* pz;
+    AGDUPSTR( pz, pzLine, "user option line" );
+    loadOptionLine( pOpts, &st, pz, DIRECTION_PROCESS, OPTION_LOAD_COOKED );
+    AGFREE( pz );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/load.c */
diff --git a/sntp/libopts/makeshell.c b/sntp/libopts/makeshell.c
new file mode 100644 (file)
index 0000000..f3bcf2c
--- /dev/null
@@ -0,0 +1,1100 @@
+
+/*
+ *  $Id: makeshell.c,v 4.6 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-20 14:06:03 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and create a Bourne shell script capable of parsing them.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tOptions*  pShellParseOptions = NULL;
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Setup Format Strings
+ */
+tSCC zStartMarker[] =
+"# # # # # # # # # # -- do not modify this marker --\n#\n"
+"#  DO NOT EDIT THIS SECTION";
+
+tSCC zPreamble[] =
+"%s OF %s\n#\n"
+"#  From here to the next `-- do not modify this marker --',\n"
+"#  the text has been generated %s\n";
+
+tSCC zEndPreamble[] =
+"#  From the %s option definitions\n#\n";
+
+tSCC zMultiDef[] = "\n"
+"if test -z \"${%1$s_%2$s}\"\n"
+"then\n"
+"  %1$s_%2$s_CT=0\n"
+"else\n"
+"  %1$s_%2$s_CT=1\n"
+"  %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
+"fi\n"
+"export %1$s_%2$s_CT";
+
+tSCC zSingleDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+tSCC zSingleNoDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LOOP START
+ *
+ *  The loop may run in either of two modes:
+ *  all options are named options (loop only)
+ *  regular, marked option processing.
+ */
+tSCC zLoopCase[] = "\n"
+"OPT_PROCESS=true\n"
+"OPT_ARG=\"$1\"\n\n"
+"while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+     /*
+      *  'OPT_ARG' may or may not match the current $1
+      */
+"    case \"${OPT_ARG}\" in\n"
+"    -- )\n"
+"        OPT_PROCESS=false\n"
+"        shift\n"
+"        ;;\n\n";
+
+tSCC zLoopOnly[] = "\n"
+"OPT_ARG=\"$1\"\n\n"
+"while [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+"    OPT_ARG=\"${1}\"\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  CASE SELECTORS
+ *
+ *  If the loop runs as a regular option loop,
+ *  then we must have selectors for each acceptable option
+ *  type (long option, flag character and non-option)
+ */
+tSCC zLongSelection[] =
+"    --* )\n";
+
+tSCC zFlagSelection[] =
+"    -* )\n";
+
+tSCC zEndSelection[] =
+"        ;;\n\n";
+
+tSCC zNoSelection[] =
+"    * )\n"
+"         OPT_PROCESS=false\n"
+"         ;;\n"
+"    esac\n\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  LOOP END
+ */
+tSCC zLoopEnd[] =
+"    if [ -n \"${OPT_ARG_VAL}\" ]\n"
+"    then\n"
+"        eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
+"        export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
+"    fi\n"
+"done\n\n"
+"unset OPT_PROCESS || :\n"
+"unset OPT_ELEMENT || :\n"
+"unset OPT_ARG || :\n"
+"unset OPT_ARG_NEEDED || :\n"
+"unset OPT_NAME || :\n"
+"unset OPT_CODE || :\n"
+"unset OPT_ARG_VAL || :\n%2$s";
+
+tSCC zTrailerMarker[] = "\n"
+"# # # # # # # # # #\n#\n"
+"#  END OF AUTOMATED OPTION PROCESSING\n"
+"#\n# # # # # # # # # # -- do not modify this marker --\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION SELECTION
+ */
+tSCC zOptionCase[] =
+"        case \"${OPT_CODE}\" in\n";
+
+tSCC zOptionPartName[] =
+"        '%s' | \\\n";
+
+tSCC zOptionFullName[] =
+"        '%s' )\n";
+
+tSCC zOptionFlag[] =
+"        '%c' )\n";
+
+tSCC zOptionEndSelect[] =
+"            ;;\n\n";
+
+tSCC zOptionUnknown[] =
+"        * )\n"
+"            echo Unknown %s: \"${OPT_CODE}\" >&2\n"
+"            echo \"$%s_USAGE_TEXT\"\n"
+"            exit 1\n"
+"            ;;\n"
+"        esac\n\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling particular options
+ */
+tSCC zTextExit[] =
+"            echo \"$%s_%s_TEXT\"\n"
+"            exit 0\n";
+
+tSCC zPagedUsageExit[] =
+"            echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
+"            exit 0\n";
+
+tSCC zCmdFmt[] =
+"            %s\n";
+
+tSCC zCountTest[] =
+"            if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
+"                echo Error:  more than %3$d %2$s options >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n";
+
+tSCC zMultiArg[] =
+"            %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
+"            OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoMultiArg[] =
+"            %1$s_%2$s_CT=0\n"
+"            OPT_ELEMENT=''\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zMayArg[]  =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=OK\n";
+
+tSCC zMustArg[] =
+"            OPT_ARG_NEEDED=YES\n";
+
+tSCC zCantArg[] =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=NO\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LONG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling long option types
+ */
+tSCC zLongOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
+"        shift\n"
+"        OPT_ARG=\"$1\"\n\n"
+"        case \"${OPT_CODE}\" in *=* )\n"
+"            OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
+"            OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
+
+tSCC zLongOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            OPT_ARG_VAL=''\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ]\n"
+"            then\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
+"            then\n"
+"                case \"${OPT_ARG}\" in -* ) ;; * )\n"
+"                    OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                    shift\n"
+"                    OPT_ARG=\"$1\" ;; esac\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FLAG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling flag option types
+ */
+tSCC zFlagOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
+"        OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
+
+tSCC zFlagOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG=-\"${OPT_ARG}\"\n"
+"            else\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
+"            else\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n"
+"                shift\n"
+"                OPT_ARG_VAL=\"$1\"\n"
+"            fi\n\n"
+"            shift\n"
+"            OPT_ARG=\"$1\"\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n\n"
+"            else\n"
+"                shift\n"
+"                if [ $# -gt 0 ]\n"
+"                then\n"
+"                    case \"$1\" in -* ) ;; * )\n"
+"                        OPT_ARG_VAL=\"$1\"\n"
+"                        shift ;; esac\n"
+"                    OPT_ARG=\"$1\"\n"
+"                fi\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+tSCC* pzShell = NULL;
+static char*  pzLeader  = NULL;
+static char*  pzTrailer = NULL;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );
+
+static void
+emitUsage( tOptions* pOpts );
+
+static void
+emitSetup( tOptions* pOpts );
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+emitFlag( tOptions* pOpts );
+
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );
+
+static void
+emitLong( tOptions* pOpts );
+
+static void
+openOutput( const char* pzFile );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionParseShell
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ *
+ * doc:
+ *  Emit a shell script that will parse the command line options.
+=*/
+void
+optionParseShell( tOptions* pOpts )
+{
+    /*
+     *  Check for our SHELL option now.
+     *  IF the output file contains the "#!" magic marker,
+     *  it will override anything we do here.
+     */
+    if (HAVE_OPT( SHELL ))
+        pzShell = OPT_ARG( SHELL );
+
+    else if (! ENABLED_OPT( SHELL ))
+        pzShell = NULL;
+
+    else if ((pzShell = getenv( "SHELL" )),
+             pzShell == NULL)
+
+        pzShell = "/bin/sh";
+
+    /*
+     *  Check for a specified output file
+     */
+    if (HAVE_OPT( SCRIPT ))
+        openOutput( OPT_ARG( SCRIPT ));
+
+    emitUsage( pOpts );
+    emitSetup( pOpts );
+
+    /*
+     *  There are four modes of option processing.
+     */
+    switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
+    case OPTPROC_LONGOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case 0:
+        fputs( zLoopOnly,        stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        break;
+
+    case OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+    }
+
+    printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker );
+    if ((pzTrailer != NULL) && (*pzTrailer != '\0'))
+        fputs( pzTrailer, stdout );
+    else if (ENABLED_OPT( SHELL ))
+        printf( "\nenv | egrep %s_\n", pOpts->pzPROGNAME );
+
+    fflush( stdout );
+    fchmod( STDOUT_FILENO, 0755 );
+    fclose( stdout );
+}
+
+
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD )
+{
+    int  nlHoldCt = 0;
+    int  pipeFd[2];
+    FILE* fp;
+
+#   define _TT_(n) tSCC z ## n [] = #n;
+    TEXTTO_TABLE
+#   undef _TT_
+#   define _TT_(n) z ## n ,
+      static const char*  apzTTNames[] = { TEXTTO_TABLE };
+#   undef _TT_
+
+    printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
+    fflush( stdout );
+
+    if (pipe( pipeFd ) != 0) {
+        fprintf( stderr, zBadPipe, errno, strerror( errno ));
+        exit( EXIT_FAILURE );
+    }
+
+    switch (fork()) {
+    case -1:
+        fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
+        exit( EXIT_FAILURE );
+        break;
+
+    case 0:
+        dup2( pipeFd[1], STDERR_FILENO );
+        dup2( pipeFd[1], STDOUT_FILENO );
+        close( pipeFd[0] );
+
+        switch (whichVar) {
+        case TT_LONGUSAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_USAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_VERSION:
+            pOD->pzLastArg = "c";
+            optionPrintVersion( pOpts, pOD );
+            /* NOTREACHED */
+
+        default:
+            exit( EXIT_FAILURE );
+        }
+
+    default:
+        close( pipeFd[1] );
+        fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
+    }
+
+    for (;;) {
+        int  ch = fgetc( fp );
+        switch (ch) {
+
+        case '\n':
+            nlHoldCt++;
+            break;
+
+        case '\'':
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputs( "'\\''", stdout );
+            break;
+
+        case EOF:
+            goto endCharLoop;
+
+        default:
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputc( ch, stdout );
+            break;
+        }
+    } endCharLoop:;
+
+    fputs( "'\n\n", stdout );
+    close( pipeFd[0] );
+}
+
+
+static void
+emitUsage( tOptions* pOpts )
+{
+    char     zTimeBuf[ AO_NAME_SIZE ];
+
+    /*
+     *  First, switch stdout to the output file name.
+     *  Then, change the program name to the one defined
+     *  by the definitions (rather than the current
+     *  executable name).  Down case the upper cased name.
+     */
+    if (pzLeader != NULL)
+        fputs( pzLeader, stdout );
+
+    {
+        tSCC    zStdout[] = "stdout";
+        tCC*    pzOutName;
+
+        {
+            time_t    curTime = time( NULL );
+            struct tm*  pTime = localtime( &curTime );
+            strftime( zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime );
+        }
+
+        if (HAVE_OPT( SCRIPT ))
+             pzOutName = OPT_ARG( SCRIPT );
+        else pzOutName = zStdout;
+
+        if ((pzLeader == NULL) && (pzShell != NULL))
+            printf( "#! %s\n", pzShell );
+
+        printf( zPreamble, zStartMarker, pzOutName, zTimeBuf );
+    }
+
+    /*
+     *  Get a copy of the original program name in lower case
+     */
+    {
+        char* pzPN = zTimeBuf;
+        tCC*  pz   = pOpts->pzPROGNAME;
+        for (;;) {
+            if ((*pzPN++ = tolower( *pz++ )) == '\0')
+                break;
+        }
+    }
+
+    printf( zEndPreamble, pOpts->pzPROGNAME );
+
+    pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf;
+    textToVariable( pOpts, TT_LONGUSAGE, NULL );
+    textToVariable( pOpts, TT_USAGE,     NULL );
+
+    {
+        tOptDesc* pOptDesc = pOpts->pOptDesc;
+        int       optionCt = pOpts->optCt;
+
+        for (;;) {
+            if (pOptDesc->pOptProc == optionPrintVersion) {
+                textToVariable( pOpts, TT_VERSION, pOptDesc );
+                break;
+            }
+
+            if (--optionCt <= 0)
+                break;
+            pOptDesc++;
+        }
+    }
+}
+
+
+static void
+emitSetup( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->presetOptCt;
+    const char* pzFmt;
+    const char* pzDefault;
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+        char zVal[16];
+
+        /*
+         *  Options that are either usage documentation or are compiled out
+         *  are not to be processed.
+         */
+        if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL))
+            continue;
+
+        if (pOptDesc->optMaxCt > 1)
+             pzFmt = zMultiDef;
+        else pzFmt = zSingleDef;
+
+        /*
+         *  IF this is an enumeration/bitmask option, then convert the value
+         *  to a string before printing the default value.
+         */
+        switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+            (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc );
+            pzDefault = pOptDesc->pzLastArg;
+            break;
+
+        /*
+         *  Numeric and membership bit options are just printed as a number.
+         */
+        case OPARG_TYPE_NUMERIC:
+        case OPARG_TYPE_MEMBERSHIP:
+            snprintf( zVal, sizeof( zVal ), "%ld", (tUL)pOptDesc->pzLastArg );
+            pzDefault = zVal;
+            break;
+
+        default:
+            if (pOptDesc->pzLastArg == NULL) {
+                if (pzFmt == zSingleDef)
+                    pzFmt = zSingleNoDef;
+                pzDefault = NULL;
+            }
+            else
+                pzDefault = pOptDesc->pzLastArg;
+        }
+
+        printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
+    }
+}
+
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionPrintVersion)
+        printf( zTextExit, pOpts->pzPROGNAME, "VERSION" );
+
+    else if (pOptDesc->pOptProc == optionPagedUsage)
+        printf( zPagedUsageExit, pOpts->pzPROGNAME );
+
+    else if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot load options files' >&2" );
+        printf( zCmdFmt, "OPT_ARG_NEEDED=YES" );
+
+    } else if (pOptDesc->pz_NAME == NULL) {
+
+        if (pOptDesc->pOptProc == NULL) {
+            printf( zCmdFmt, "echo 'Warning:  Cannot save options files' "
+                    ">&2" );
+            printf( zCmdFmt, "OPT_ARG_NEEDED=OK" );
+        } else
+            printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" );
+
+    } else {
+        if (pOptDesc->optMaxCt == 1)
+            printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        else {
+            if ((unsigned)pOptDesc->optMaxCt < NOLIMIT)
+                printf( zCountTest, pOpts->pzPROGNAME,
+                        pOptDesc->pz_NAME, pOptDesc->optMaxCt );
+
+            printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        }
+
+        /*
+         *  Fix up the args.
+         */
+        if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) {
+            printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) {
+            printf( zMayArg,  pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else {
+            fputs( zMustArg, stdout );
+        }
+    }
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot suppress the loading of "
+                "options files' >&2" );
+
+    } else if (pOptDesc->optMaxCt == 1)
+        printf( zNoSingleArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+    else
+        printf( zNoMultiArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+
+    printf( zCmdFmt, "OPT_ARG_NEEDED=NO" );
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+emitFlag( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+
+        if (SKIP_OPT(pOptDesc))
+            continue;
+
+        if (isprint( pOptDesc->optValue )) {
+            printf( zOptionFlag, pOptDesc->optValue );
+            printOptionAction( pOpts, pOptDesc );
+        }
+    }
+    printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
+}
+
+
+/*
+ *  Emit the match text for a long option
+ */
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       oCt = pOpts->optCt;
+    int       min = 1;
+    char      zName[ 256 ];
+    char*     pz  = zName;
+
+    for (;;) {
+        int matchCt = 0;
+
+        /*
+         *  Omit the current option, Documentation opts and compiled out opts.
+         */
+        if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
+            if (--oCt <= 0)
+                break;
+            pOD++;
+            continue;
+        }
+
+        /*
+         *  Check each character of the name case insensitively.
+         *  They must not be the same.  They cannot be, because it would
+         *  not compile correctly if they were.
+         */
+        while (  toupper( pOD->pz_Name[matchCt] )
+              == toupper( pzMatchName[matchCt] ))
+            matchCt++;
+
+        if (matchCt > min)
+            min = matchCt;
+
+        /*
+         *  Check the disablement name, too.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            matchCt = 0;
+            while (  toupper( pOD->pz_DisableName[matchCt] )
+                  == toupper( pzMatchName[matchCt] ))
+                matchCt++;
+            if (matchCt > min)
+                min = matchCt;
+        }
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF the 'min' is all or one short of the name length,
+     *  THEN the entire string must be matched.
+     */
+    if (  (pzMatchName[min  ] == NUL)
+       || (pzMatchName[min+1] == NUL) )
+        printf( zOptionFullName, pzMatchName );
+
+    else {
+        int matchCt = 0;
+        for (; matchCt <= min; matchCt++)
+            *pz++ = pzMatchName[matchCt];
+
+        for (;;) {
+            *pz = NUL;
+            printf( zOptionPartName, zName );
+            *pz++ = pzMatchName[matchCt++];
+            if (pzMatchName[matchCt] == NUL) {
+                *pz = NUL;
+                printf( zOptionFullName, zName );
+                break;
+            }
+        }
+    }
+}
+
+
+/*
+ *  Emit GNU-standard long option handling code
+ */
+static void
+emitLong( tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       ct  = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    /*
+     *  do each option, ...
+     */
+    do  {
+        /*
+         *  Documentation & compiled-out options
+         */
+        if (SKIP_OPT(pOD))
+            continue;
+
+        emitMatchExpr( pOD->pz_Name, pOD, pOpts );
+        printOptionAction( pOpts, pOD );
+
+        /*
+         *  Now, do the same thing for the disablement version of the option.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
+            printOptionInaction( pOpts, pOD );
+        }
+    } while (pOD++, --ct > 0);
+
+    printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
+}
+
+
+static void
+openOutput( const char* pzFile )
+{
+    FILE* fp;
+    char* pzData = NULL;
+    struct stat stbf;
+
+    do  {
+        char*  pzScan;
+        int    sizeLeft;
+
+        /*
+         *  IF we cannot stat the file,
+         *  THEN assume we are creating a new file.
+         *       Skip the loading of the old data.
+         */
+        if (stat( pzFile, &stbf ) != 0)
+            break;
+
+        /*
+         *  The file must be a regular file
+         */
+        if (! S_ISREG( stbf.st_mode )) {
+            fprintf( stderr, zNotFile, pzFile );
+            exit( EXIT_FAILURE );
+        }
+
+        pzData = (char*)malloc( stbf.st_size + 1 );
+        fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG );
+
+        sizeLeft = stbf.st_size;
+        pzScan   = pzData;
+
+        /*
+         *  Read in all the data as fast as our OS will let us.
+         */
+        for (;;) {
+            int inct = fread( (void*)pzScan, 1, sizeLeft, fp );
+            if (inct == 0)
+                break;
+
+            pzScan   += inct;
+            sizeLeft -= inct;
+
+            if (sizeLeft == 0)
+                break;
+        }
+
+        /*
+         *  NUL-terminate the leader and look for the trailer
+         */
+        *pzScan = '\0';
+        fclose( fp );
+        pzScan  = strstr( pzData, zStartMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        *(pzScan++) = NUL;
+        pzScan  = strstr( pzScan, zTrailerMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        /*
+         *  Check to see if the data contains
+         *  our marker.  If it does, then we will skip over it
+         */
+        pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1;
+        pzLeader  = pzData;
+    } while (AG_FALSE);
+
+    freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout );
+}
+
+
+/*=export_func genshelloptUsage
+ * private:
+ * what: The usage function for the genshellopt generated program
+ *
+ * arg:  + tOptions* + pOpts    + program options descriptor +
+ * arg:  + int       + exitCode + usage text type to produce +
+ *
+ * doc:
+ *  This function is used to create the usage strings for the option
+ *  processing shell script code.  Two child processes are spawned
+ *  each emitting the usage text in either the short (error exit)
+ *  style or the long style.  The generated program will capture this
+ *  and create shell script variables containing the two types of text.
+=*/
+void
+genshelloptUsage( tOptions*  pOpts, int exitCode )
+{
+    /*
+     *  IF not EXIT_SUCCESS,
+     *  THEN emit the short form of usage.
+     */
+    if (exitCode != EXIT_SUCCESS)
+        optionUsage( pOpts, exitCode );
+    fflush( stderr );
+    fflush( stdout );
+
+    option_usage_fp = stdout;
+
+    /*
+     *  First, print our usage
+     */
+    switch (fork()) {
+    case -1:
+        optionUsage( pOpts, EXIT_FAILURE );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        optionUsage( pOpts, EXIT_SUCCESS );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    /*
+     *  Generate the pzProgName, since optionProcess() normally
+     *  gets it from the command line
+     */
+    {
+        char* pz;
+        AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" );
+        pShellParseOptions->pzProgName = pz;
+        while (*pz != NUL) {
+            *pz = tolower( *pz );
+            pz++;
+        }
+    }
+
+    /*
+     *  Separate the makeshell usage from the client usage
+     */
+    fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName );
+    fflush( option_usage_fp );
+
+    /*
+     *  Now, print the client usage.
+     */
+    switch (fork()) {
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        /*FALLTHROUGH*/
+    case -1:
+        optionUsage( pShellParseOptions, EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/makeshell.c */
diff --git a/sntp/libopts/nested.c b/sntp/libopts/nested.c
new file mode 100644 (file)
index 0000000..be60bd3
--- /dev/null
@@ -0,0 +1,705 @@
+
+/*
+ *  $Id: nested.c,v 4.3 2005/07/27 17:26:32 bkorb Exp $
+ *  Time-stamp:      "2005-07-27 10:10:28 bkorb"
+ *
+ *   Automated Options Nested Values module.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+removeBackslashes( char* pzSrc );
+
+static const char*
+scanQuotedString( const char* pzTxt );
+
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode );
+
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static void
+unloadNestedArglist( tArgList* pAL );
+
+static void
+sortNestedList( tArgList* pAL );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*  removeBackslashes
+ *
+ *  This function assumes that all newline characters were preceeded by
+ *  backslashes that need removal.
+ */
+static void
+removeBackslashes( char* pzSrc )
+{
+    char* pzD = strchr(pzSrc, '\n');
+
+    if (pzD == NULL)
+        return;
+    *--pzD = '\n';
+
+    for (;;) {
+        char ch = ((*pzD++) = *(pzSrc++));
+        switch (ch) {
+        case '\n': *--pzD = ch; break;
+        case NUL:  return;
+        default:
+            ;
+        }
+    }
+}
+
+
+/*  scanQuotedString
+ *
+ *  Find the end of a quoted string, skipping escaped quote characters.
+ */
+static const char*
+scanQuotedString( const char* pzTxt )
+{
+    char q = *(pzTxt++); /* remember the type of quote */
+
+    for (;;) {
+        char ch = *(pzTxt++);
+        if (ch == NUL)
+            return pzTxt-1;
+
+        if (ch == q)
+            return pzTxt;
+
+        if (ch == '\\') {
+            ch = *(pzTxt++);
+            /*
+             *  IF the next character is NUL, drop the backslash, too.
+             */
+            if (ch == NUL)
+                return pzTxt - 2;
+
+            /*
+             *  IF the quote character or the escape character were escaped,
+             *  then skip both, as long as the string does not end.
+             */
+            if ((ch == q) || (ch == '\\')) {
+                if (*(pzTxt++) == NUL)
+                    return pzTxt-1;
+            }
+        }
+    }
+}
+
+
+/*  addStringValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + dataLen + sizeof(*pNV);
+
+    pNV = AGALOC( sz, "option name/str value pair" );
+    if (pNV == NULL)
+        return NULL;
+
+    if (pzValue == NULL) {
+        pNV->valType = OPARG_TYPE_NONE;
+        pNV->pzName = pNV->v.strVal;
+
+    } else {
+        pNV->valType = OPARG_TYPE_STRING;
+        if (dataLen > 0)
+            memcpy( pNV->v.strVal, pzValue, dataLen );
+        pNV->v.strVal[dataLen] = NUL;
+        pNV->pzName = pNV->v.strVal + dataLen + 1;
+    }
+
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addBoolValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else if (isdigit( *pzValue ))
+        pNV->v.boolVal = atoi( pzValue );
+    else switch (*pzValue) {
+    case 'f':
+    case 'F':
+    case 'n':
+    case 'N':
+        pNV->v.boolVal = 0; break;
+    default:
+        pNV->v.boolVal = 1;
+    }
+
+    pNV->valType = OPARG_TYPE_BOOLEAN;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNumberValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else
+        pNV->v.boolVal = atoi( pzValue );
+
+    pNV->valType = OPARG_TYPE_NUMERIC;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNestedValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+
+    if (dataLen == 0) {
+        size_t sz = nameLen + sizeof(*pNV) + 1;
+        pNV = AGALOC( sz, "empty nested value pair" );
+        if (pNV == NULL)
+            return NULL;
+        pNV->v.nestVal = NULL;
+        pNV->valType = OPARG_TYPE_HIERARCHY;
+        pNV->pzName = (char*)(pNV + 1);
+        memcpy( pNV->pzName, pzName, nameLen );
+        pNV->pzName[ nameLen ] = NUL;
+
+    } else {
+        pNV = optionLoadNested( pzValue, pzName, nameLen, mode );
+    }
+
+    if (pNV != NULL)
+        addArgListEntry( pp, pNV );
+
+    return pNV;
+}
+
+
+/*  scanNameEntry
+ *
+ *  We have an entry that starts with a name.  Find the end of it, cook it
+ *  (if called for) and create the name/value association.
+ */
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+    const char* pzScan = pzName+1;
+    const char* pzVal;
+    size_t nameLen = 1;
+    size_t dataLen = 0;
+
+    while (ISNAMECHAR( *pzScan ))  { pzScan++; nameLen++; }
+
+    while (isspace( *pzScan )) {
+        char ch = *(pzScan++);
+        if ((ch == '\n') || (ch == ',')) {
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+            return pzScan - 1;
+        }
+    }
+
+    switch (*pzScan) {
+    case '=':
+    case ':':
+        while (isspace( *++pzScan ))  ;
+        switch (*pzScan) {
+        case ',':  goto comma_char;
+        case '"':
+        case '\'': goto quote_char;
+        case NUL:  addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0);
+                   goto leave_scan_name;
+        default:   goto default_char;
+        }
+
+    case ',':
+    comma_char:
+        pzScan++;
+        /* FALLTHROUGH */
+
+    case NUL:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case '"':
+    case '\'':
+    quote_char:
+        pzVal = pzScan;
+        pzScan = scanQuotedString( pzScan );
+        dataLen = pzScan - pzVal;
+        pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                              pzVal, dataLen );
+        if ((pNV != NULL) && (mode == OPTION_LOAD_COOKED))
+            ao_string_cook( pNV->v.strVal, NULL );
+        break;
+
+    default:
+    default_char:
+        /*
+         *  We have found some strange text value.  It ends with a newline
+         *  or a comma.
+         */
+        pzVal = pzScan;
+        for (;;) {
+            char ch = *(pzScan++);
+            switch (ch) {
+            case '\n':
+                if ((pzScan > pzVal + 2) && (pzScan[-2] == '\\'))
+                    continue;
+                /* FALLTHROUGH */
+
+            case ',':
+                dataLen = (pzScan - pzVal) - 1;
+                pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                                      pzVal, dataLen );
+                if (pNV != NULL)
+                    removeBackslashes( pNV->v.strVal );
+                goto leave_scan_name;
+            }
+        }
+        break;
+    } leave_scan_name:;
+
+    return pzScan;
+}
+
+
+/*  scanXmlEntry
+ *
+ *  We've found a '<' character.  We ignore this if it is a comment or a
+ *  directive.  If it is something else, then whatever it is we are looking
+ *  at is bogus.  Returning NULL stops processing.
+ */
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    size_t nameLen = 1, valLen = 0;
+    const char*   pzScan = ++pzName;
+    const char*   pzVal;
+    tOptionValue  valu;
+    tOptionValue* pNewVal;
+
+    if (! isalpha(*pzName)) {
+        switch (*pzName) {
+        default:
+            pzName = NULL;
+            break;
+
+        case '!':
+            pzName = strstr( pzName, "-->" );
+            if (pzName != NULL)
+                pzName += 3;
+            break;
+
+        case '?':
+            pzName = strchr( pzName, '>' );
+            if (pzName != NULL)
+                pzName++;
+            break;
+        }
+        return pzName;
+    }
+
+    while (isalpha( *++pzScan ))  nameLen++;
+    if (nameLen > 64)
+        return NULL;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzScan) {
+    case ' ':
+    case '\t':
+        pzScan = parseAttributes( NULL, (char*)pzScan, &mode, &valu );
+        if (*pzScan == '>') {
+            pzScan++;
+            break;
+        }
+
+        if (*pzScan != '/')
+            return NULL;
+        /* FALLTHROUGH */
+
+    case '/':
+        if (*++pzScan != '>')
+            return NULL;
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        return pzScan+2;
+
+    default:  return NULL;
+    case '>': break;
+    }
+
+    pzVal = pzScan;
+
+    {
+        char z[68];
+        char* pzD = z;
+        int  ct = nameLen;
+        const char* pzS = pzName;
+
+        *(pzD++) = '<';
+        *(pzD++) = '/';
+
+        do  {
+            *(pzD++) = *(pzS++);
+        } while (--ct > 0);
+        *(pzD++) = '>';
+        *pzD = NUL;
+
+        pzScan = strstr( pzScan, z );
+        if (pzScan == NULL)
+            return NULL;
+        valLen = (pzScan - pzVal);
+        pzScan += nameLen + 3;
+        while (isspace( *pzScan ))  pzScan++;
+    }
+
+    switch (valu.valType) {
+    case OPARG_TYPE_NONE:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case OPARG_TYPE_STRING:
+        pNewVal =
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        if (mode == OPTION_LOAD_KEEP)
+            break;
+        mungeString( pNewVal->v.strVal, mode );
+        break;
+
+    case OPARG_TYPE_BOOLEAN:
+        addBoolValue(   &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_NUMERIC:
+        addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_HIERARCHY:
+    {
+        char* pz = AGALOC( valLen+1, "hierarchical scan" );
+        if (pz == NULL)
+            break;
+        memcpy( pz, pzVal, valLen );
+        pz[valLen] = NUL;
+        addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen, mode );
+        free(pz);
+        break;
+    }
+
+    case OPARG_TYPE_ENUMERATION:
+    case OPARG_TYPE_MEMBERSHIP:
+    default:
+        break;
+    }
+
+    return pzScan;
+}
+
+
+static void
+unloadNestedArglist( tArgList* pAL )
+{
+    int ct = pAL->useCt;
+    tOptionValue** ppNV = (tOptionValue**)(pAL->apzArgs);
+
+    while (ct-- > 0) {
+        tOptionValue* pNV = *(ppNV++);
+        if (pNV->valType == OPARG_TYPE_HIERARCHY)
+            unloadNestedArglist( pNV->v.nestVal );
+        free( pNV );
+    }
+
+    free( (void*)pAL );
+}
+
+
+/*=export_func  optionUnloadNested
+ *
+ * what:  Deallocate the memory for a nested value
+ * arg:   + const tOptionValue* + pOptVal + the hierarchical value +
+ *
+ * doc:
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+=*/
+void
+optionUnloadNested( const tOptionValue* pOV )
+{
+    if (pOV == NULL) return;
+    if (pOV->valType != OPARG_TYPE_HIERARCHY) {
+        errno = EINVAL;
+        return;
+    }
+
+    unloadNestedArglist( pOV->v.nestVal );
+
+    free( (void*)pOV );
+}
+
+
+/*  sortNestedList
+ *
+ *  This is a _stable_ sort.  The entries are sorted alphabetically,
+ *  but within entries of the same name the ordering is unchanged.
+ *  Typically, we also hope the input is sorted.
+ */
+static void
+sortNestedList( tArgList* pAL )
+{
+    int ix;
+    int lm = pAL->useCt;
+
+    /*
+     *  This loop iterates "useCt" - 1 times.
+     */
+    for (ix = 0; ++ix < lm;) {
+        int iy = ix-1;
+        tOptionValue* pNewNV = (tOptionValue*)pAL->apzArgs[ix];
+        tOptionValue* pOldNV = (tOptionValue*)pAL->apzArgs[iy];
+
+        /*
+         *  For as long as the new entry precedes the "old" entry,
+         *  move the old pointer.  Stop before trying to extract the
+         *  "-1" entry.
+         */
+        while (strcmp( pOldNV->pzName, pNewNV->pzName ) > 0) {
+            pAL->apzArgs[iy+1] = (void*)pOldNV;
+            pOldNV = (tOptionValue*)pAL->apzArgs[--iy];
+            if (iy < 0)
+                break;
+        }
+
+        /*
+         *  Always store the pointer.  Sometimes it is redundant,
+         *  but the redundancy is cheaper than a test and branch sequence.
+         */
+        pAL->apzArgs[iy+1] = (void*)pNewNV;
+    }
+}
+
+
+/*=export_func  optionLoadNested
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + const char*     + pzTxt   + the text to scan +
+ * arg:   + const char*     + pzName  + the name for the text +
+ * arg:   + size_t          + nameLen + the length of "name"  +
+ * arg:   + tOptionLoadMode + mode    + the value formation mode    +
+ *
+ * ret_type:  tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  A block of text represents a series of values.  It may be an
+ *  entire configuration file, or it may be an argument to an
+ *  option that takes a hierarchical value.
+=*/
+tOptionValue*
+optionLoadNested( const char* pzTxt, const char* pzName, size_t nameLen,
+                  tOptionLoadMode mode )
+{
+    tOptionValue* pRes;
+    tArgList*     pAL;
+
+    /*
+     *  Make sure we have some data and we have space to put what we find.
+     */
+    if (pzTxt == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+    while (isspace( *pzTxt ))  pzTxt++;
+    if (*pzTxt == NUL) {
+        errno = ENOENT;
+        return NULL;
+    }
+    pRes = AGALOC( sizeof(*pRes) + nameLen + 1, "nested args" );
+    if (pRes == NULL) {
+        errno = ENOMEM;
+        return NULL;
+    }
+    pRes->valType   = OPARG_TYPE_HIERARCHY;
+    pRes->pzName    = (char*)(pRes + 1);
+    memcpy( pRes->pzName, pzName, nameLen );
+    pRes->pzName[ nameLen ] = NUL;
+
+    pAL = AGALOC( sizeof(*pAL), "nested arg list" );
+    if (pAL == NULL) {
+        free( pRes );
+        return NULL;
+    }
+    pRes->v.nestVal = pAL;
+    pAL->useCt   = 0;
+    pAL->allocCt = MIN_ARG_ALLOC_CT;
+
+    /*
+     *  Scan until we hit a NUL.
+     */
+    do  {
+        while (isspace( *pzTxt ))  pzTxt++;
+        if (isalpha( *pzTxt )) {
+            pzTxt = scanNameEntry( pzTxt, pRes, mode );
+        }
+        else switch (*pzTxt) {
+        case NUL: goto scan_done;
+        case '<': pzTxt = scanXmlEntry( pzTxt, pRes, mode );
+                  if (*pzTxt == ',') pzTxt++; break;
+        case '#': pzTxt = strchr( pzTxt, '\n' );             break;
+        default:  goto woops;
+        }
+    } while (pzTxt != NULL); scan_done:;
+
+    pAL = pRes->v.nestVal;
+    if (pAL->useCt != 0) {
+        sortNestedList( pAL );
+        return pRes;
+    }
+
+ woops:
+    free( pRes->v.nestVal );
+    free( pRes );
+    return NULL;
+}
+
+
+/*=export_func  optionNestedVal
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Nested value was found on the command line
+=*/
+void
+optionNestedVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    tOptionValue* pOV =
+        optionLoadNested(pOD->pzLastArg, pOD->pz_Name, strlen( pOD->pz_Name ),
+                         OPTION_LOAD_UNCOOKED);
+
+    if (pOV != NULL)
+        addArgListEntry( &(pOD->optCookie), (void*)pOV );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/nested.c */
diff --git a/sntp/libopts/numeric.c b/sntp/libopts/numeric.c
new file mode 100644 (file)
index 0000000..86c1625
--- /dev/null
@@ -0,0 +1,89 @@
+
+/*
+ *  $Id: numeric.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 08:22:56 bkorb"
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionNumericVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a numeric value.
+=*/
+void
+optionNumericVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    char* pz;
+    long  val;
+
+    /*
+     *  Numeric options may have a range associated with it.
+     *  If it does, the usage procedure requests that it be
+     *  emitted by passing a NULL pOD pointer.
+     */
+    if ((pOD == NULL) || (pOD->pzLastArg == NULL))
+        return;
+
+    val = strtol( pOD->pzLastArg, &pz, 0 );
+    if (*pz != NUL) {
+        fprintf( stderr, zNotNumber, pOpts->pzProgName, pOD->pzLastArg );
+        (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
+    }
+
+    pOD->pzLastArg = (char*)val;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/numeric.c */
diff --git a/sntp/libopts/pgusage.c b/sntp/libopts/pgusage.c
new file mode 100644 (file)
index 0000000..4a1b3dd
--- /dev/null
@@ -0,0 +1,154 @@
+
+/*
+ *  $Id: pgusage.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-14 08:22:01 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tePagerState pagerState = PAGER_STATE_INITIAL;
+
+/*=export_func  optionPagedUsage
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Run the usage output through a pager.
+ *  This is very handy if it is very long.
+=*/
+void
+optionPagedUsage( tOptions* pOptions, tOptDesc* pOD )
+{
+    static pid_t     my_pid;
+    char zPageUsage[ 1024 ];
+
+    /*
+     *  IF we are being called after the usage proc is done
+     *     (and thus has called "exit(2)")
+     *  THEN invoke the pager to page through the usage file we created.
+     */
+    switch (pagerState) {
+    case PAGER_STATE_INITIAL:
+    {
+        my_pid  = getpid();
+#ifdef HAVE_SNPRINTF
+        snprintf( zPageUsage, sizeof(zPageUsage), "/tmp/use.%lu", (tUL)my_pid );
+#else
+        sprintf( zPageUsage, "/tmp/use.%lu", (tUL)my_pid );
+#endif
+        unlink( zPageUsage );
+
+        /*
+         *  Set usage output to this temporary file
+         */
+        option_usage_fp = fopen( zPageUsage, "w" FOPEN_BINARY_FLAG );
+        if (option_usage_fp == NULL)
+            _exit( EXIT_FAILURE );
+
+        pagerState = PAGER_STATE_READY;
+
+        /*
+         *  Set up so this routine gets called during the exit logic
+         */
+        atexit( (void(*)(void))optionPagedUsage );
+
+        /*
+         *  The usage procedure will now put the usage information into
+         *  the temporary file we created above.
+         */
+        (*pOptions->pUsageProc)( pOptions, EXIT_SUCCESS );
+
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+    }
+
+    case PAGER_STATE_READY:
+    {
+        tSCC zPage[]  = "%1$s /tmp/use.%2$lu ; rm -f /tmp/use.%2$lu";
+        char* pzPager = getenv( "PAGER" );
+
+        /*
+         *  Use the "more(1)" program if "PAGER" has not been defined
+         */
+        if (pzPager == NULL)
+            pzPager = "more";
+
+        /*
+         *  Page the file and remove it when done.
+         */
+#ifdef HAVE_SNPRINTF
+        snprintf( zPageUsage, sizeof(zPageUsage), zPage, pzPager, (tUL)my_pid );
+#else
+        sprintf( zPageUsage, zPage, pzPager, (tUL)my_pid );
+#endif
+        fclose( stderr );
+        dup2( STDOUT_FILENO, STDERR_FILENO );
+
+        system( zPageUsage );
+    }
+
+    case PAGER_STATE_CHILD:
+        /*
+         *  This is a child process used in creating shell script usage.
+         */
+        break;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/pgusage.c */
diff --git a/sntp/libopts/proto.h b/sntp/libopts/proto.h
new file mode 100644 (file)
index 0000000..cebc82a
--- /dev/null
@@ -0,0 +1,124 @@
+/* -*- buffer-read-only: t -*- vi: set ro:
+ *
+ * Prototypes for autoopts
+ * Generated Thu Jul 28 16:19:17 PDT 2005
+ */
+#ifndef AUTOOPTS_PROTO_H_GUARD
+#define AUTOOPTS_PROTO_H_GUARD
+#ifndef LOCAL
+#  define LOCAL extern
+#  define REDEF_LOCAL 1
+#else
+#  undef  REDEF_LOCAL
+#endif
+/*
+ *  Extracted from autoopts.c
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState );
+
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState );
+
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tUC optValue, tOptState* pOptState );
+
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts );
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts );
+
+/*
+ *  Extracted from configfile.c
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts );
+
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType );
+
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram );
+
+/*
+ *  Extracted from cook.c
+ */
+/*
+ *  Extracted from enumeration.c
+ */
+/*
+ *  Extracted from environment.c
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type );
+
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type );
+
+/*
+ *  Extracted from load.c
+ */
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode );
+
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode );
+
+/*
+ *  Extracted from makeshell.c
+ */
+/*
+ *  Extracted from nested.c
+ */
+/*
+ *  Extracted from putshell.c
+ */
+/*
+ *  Extracted from save.c
+ */
+/*
+ *  Extracted from sort.c
+ */
+LOCAL void
+optionSort( tOptions* pOpts );
+
+/*
+ *  Extracted from stack.c
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry );
+
+/*
+ *  Extracted from text_mmap.c
+ */
+LOCAL void*
+text_mmap( const char* pzFile, int prot, int flags, tmap_info_t* pMI );
+
+LOCAL int
+text_munmap( tmap_info_t* pMI );
+
+/*
+ *  Extracted from tokenize.c
+ */
+/*
+ *  Extracted from usage.c
+ */
+/*
+ *  Extracted from version.c
+ */
+#ifdef REDEF_LOCAL
+#  undef LOCAL
+#  define LOCAL
+#endif
+
+#endif /* AUTOOPTS_PROTO_H_GUARD */
diff --git a/sntp/libopts/putshell.c b/sntp/libopts/putshell.c
new file mode 100644 (file)
index 0000000..f445d57
--- /dev/null
@@ -0,0 +1,333 @@
+
+/*
+ *  $Id: putshell.c,v 4.6 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-14 14:55:01 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and print them to standard out in a fashion that
+ *  will allow them to be interpreted by the Bourne or Korn shells.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+putQuotedStr( tCC* pzStr );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  Make sure embedded single quotes come out okay.  The initial quote has
+ *  been emitted and the closing quote will be upon return.
+ */
+static void
+putQuotedStr( tCC* pzStr )
+{
+    /*
+     *  Handle empty strings to make the rese of the logic simpler.
+     */
+    if ((pzStr == NULL) || (*pzStr == NUL)) {
+        fputs( "''", stdout );
+        return;
+    }
+
+    /*
+     *  Emit any single quotes/apostrophes at the start of the string and
+     *  bail if that is all we need to do.
+     */
+    while (*pzStr == '\'') {
+        fputs( "\\'", stdout );
+        pzStr++;
+    }
+    if (*pzStr == NUL)
+        return;
+
+    /*
+     *  Start the single quote string
+     */
+    fputc( '\'', stdout );
+    for (;;) {
+        tCC* pz = strchr( pzStr, '\'' );
+        if (pz == NULL)
+            break;
+
+        /*
+         *  Emit the string up to the single quote (apostrophe) we just found.
+         */
+        fwrite( pzStr, (pz - pzStr), 1, stdout );
+        fputc( '\'', stdout );
+        pzStr = pz;
+
+        /*
+         *  Emit an escaped apostrophe for every one we find.
+         *  If that ends the string, do not re-open the single quotes.
+         */
+        while (*++pzStr == '\'')   fputs( "\\'", stdout );
+        if (*pzStr == NUL)
+            return;
+
+        fputc( '\'', stdout );
+    }
+
+    /*
+     *  If we broke out of the loop, we must still emit the remaining text
+     *  and then close the single quote string.
+     */
+    fputs( pzStr, stdout );
+    fputc( '\'', stdout );
+}
+
+
+/*=export_func  optionPutShell
+ * what:  write a portable shell script to parse options
+ * private:
+ * arg:   tOptions*, pOpts, the program options descriptor
+ * doc:   This routine will emit portable shell script text for parsing
+ *        the options described in the option definitions.
+=*/
+void
+optionPutShell( tOptions* pOpts )
+{
+    int  optIx = 0;
+    tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
+    tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
+    tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
+    tSCC zOptValFmt[] = "%s_%s=";
+    tSCC zOptEnd[]    = "\nexport %s_%s\n";
+    tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
+    tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";
+
+    printf( zOptCtFmt, pOpts->curOptIdx-1 );
+
+    do  {
+        tOptDesc* pOD = pOpts->pOptDesc + optIx;
+
+        if (SKIP_OPT(pOD))
+            continue;
+
+        /*
+         *  Equivalence classes are hard to deal with.  Where the
+         *  option data wind up kind of squishes around.  For the purposes
+         *  of emitting shell state, they are not recommended, but we'll
+         *  do something.  I guess we'll emit the equivalenced-to option
+         *  at the point in time when the base option is found.
+         */
+        if (pOD->optEquivIndex != NO_EQUIVALENT)
+            continue; /* equivalence to a different option */
+
+        /*
+         *  Equivalenced to a different option.  Process the current option
+         *  as the equivalenced-to option.  Keep the persistent state bits,
+         *  but copy over the set-state bits.
+         */
+        if (pOD->optActualIndex != optIx) {
+            tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex;
+            p->pzLastArg = pOD->pzLastArg;
+            p->fOptState &= OPTST_PERSISTENT;
+            p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT;
+            printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME );
+            pOD = p;
+        }
+
+        /*
+         *  If the argument type is a set membership bitmask, then we always
+         *  emit the thing.  We do this because it will always have some sort
+         *  of bitmask value and we need to emit the bit values.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
+            char* pz;
+            uintptr_t val = 1;
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->optCookie) );
+            pOD->optCookie = (void*)(uintptr_t)~0UL;
+            (*(pOD->pOptProc))( (tOptions*)2UL, pOD );
+
+            /*
+             *  We are building the typeset list.  The list returned starts with
+             *  'none + ' for use by option saving stuff.  We must ignore that.
+             */
+            pz = (char*)pOD->pzLastArg + 7;
+            while (*pz != NUL) {
+                printf( "typeset -x -i %s_", pOD->pz_NAME );
+                pz += strspn( pz, " +\t\n\f" );
+                for (;;) {
+                    char ch = *(pz++);
+                         if (islower( ch ))  fputc( toupper( ch ), stdout );
+                    else if (isalnum( ch ))  fputc( ch, stdout );
+                    else if (isspace( ch )
+                          || (ch == '+'))    goto name_done;
+                    else if (ch == NUL)      { pz--; goto name_done; }
+                    else fputc( '_', stdout );
+                } name_done:;
+                printf( "=%1$d # 0x%1$X\n", val );
+                val <<= 1;
+            }
+            free( (void*)(pOD->pzLastArg) );
+            continue;
+        }
+
+        /*
+         *  IF the option was either specified or it wakes up enabled,
+         *  then we will emit information.  Otherwise, skip it.
+         *  The idea is that if someone defines an option to initialize
+         *  enabled, we should tell our shell script that it is enabled.
+         */
+        if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD ))
+            continue;
+
+        /*
+         *  Handle stacked arguments
+         */
+        if (  (pOD->fOptState & OPTST_STACKED)
+           && (pOD->optCookie != NULL) )  {
+            tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";
+
+            tArgList*    pAL = (tArgList*)pOD->optCookie;
+            tCC**        ppz = pAL->apzArgs;
+            int          ct  = pAL->useCt;
+
+            printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct );
+
+            while (--ct >= 0) {
+                tSCC zOptNumArg[] = "%s_%s_%d=";
+                tSCC zOptEnd[]    = "\nexport %s_%s_%d\n";
+
+                printf( zOptNumArg, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+                putQuotedStr( *(ppz++) );
+                printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+            }
+        }
+
+        /*
+         *  If the argument has been disabled,
+         *  Then set its value to the disablement string
+         */
+        else if ((pOD->fOptState & OPTST_DISABLED) != 0)
+            printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (pOD->pz_DisablePfx != NULL)
+                    ? pOD->pz_DisablePfx : "false" );
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->pzLastArg) );
+
+        /*
+         *  If the argument type is an enumeration, then it is much
+         *  like a text value, except we call the callback function
+         *  to emit the value corresponding to the "pzLastArg" number.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            fputc( '\'', stdout );
+            (*(pOD->pOptProc))( (tOptions*)1UL, pOD );
+            fputc( '\'', stdout );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN)
+            printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    ((uintptr_t)(pOD->pzLastArg) == 0) ? "false" : "true" );
+
+        /*
+         *  IF the option has an empty value,
+         *  THEN we set the argument to the occurrence count.
+         */
+        else if (  (pOD->pzLastArg == NULL)
+                || (pOD->pzLastArg[0] == NUL) )
+
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (int)pOD->optOccCt );
+
+        /*
+         *  This option has a text value
+         */
+        else {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            putQuotedStr( pOD->pzLastArg );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+    } while (++optIx < pOpts->presetOptCt );
+
+    if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+       && (pOpts->curOptIdx < pOpts->origArgCt)) {
+        fputs( "set --", stdout );
+        for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
+            char* pzArg = pOpts->origArgVect[ optIx ];
+            if (strchr( pzArg, '\'' ) == NULL)
+                printf( " '%s'", pzArg );
+            else {
+                fputs( " '", stdout );
+                for (;;) {
+                    char ch = *(pzArg++);
+                    switch (ch) {
+                    case '\'':  fputs( "'\\''", stdout ); break;
+                    case NUL:   goto arg_done;
+                    default:    fputc( ch, stdout ); break;
+                    }
+                } arg_done:;
+                fputc( '\'', stdout );
+            }
+        }
+        fputs( "\nOPTION_CT=0\n", stdout );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/putshell.c */
diff --git a/sntp/libopts/restore.c b/sntp/libopts/restore.c
new file mode 100644 (file)
index 0000000..3d9cf7c
--- /dev/null
@@ -0,0 +1,207 @@
+
+/*
+ *  restore.c  $Id: restore.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-23 15:10:20 bkorb"
+ *
+ *  This module's routines will save the current option state to memory
+ *  and restore it.  If saved prior to the initial optionProcess call,
+ *  then the initial state will be restored.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func optionSaveState
+ *
+ * what:  saves the option state to memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   This routine will allocate enough memory to save the current
+ *        option processing state.  If this routine has been called before,
+ *        that memory will be reused.  You may only save one copy of the
+ *        option state.  This routine may be called before optionProcess(3AO).
+ *        If you do call it before the first call to optionProcess, then
+ *        you may also change the contents of argc/argv after you call
+ *        optionRestore(3AO)
+ *
+ * err:   If it fails to allocate the memory,
+ *        it will print a message to stderr and exit.
+ *        Otherwise, it will always succeed.
+=*/
+void
+optionSaveState( tOptions* pOpts )
+{
+    if (pOpts->pSavedState == NULL) {
+        size_t sz = sizeof( *pOpts ) + (pOpts->optCt * sizeof( tOptDesc ));
+        pOpts->pSavedState = AGALOC( sz, "saved option state" );
+        if (pOpts->pSavedState == NULL) {
+            tCC* pzName = pOpts->pzProgName;
+            if (pzName == NULL) {
+                pzName = pOpts->pzPROGNAME;
+                if (pzName == NULL)
+                    pzName = zNil;
+            }
+            fprintf( stderr, zCantSave, pzName, sz );
+            exit( EXIT_FAILURE );
+        }
+    }
+
+    {
+        tOptions* p   = pOpts->pSavedState;
+        tOptDesc* pOD = pOpts->pOptDesc;
+        int       ct  = pOpts->optCt;
+
+        memcpy( p, pOpts, sizeof( *p ));
+        memcpy( p + 1, pOpts->pOptDesc, p->optCt * sizeof( tOptDesc ));
+
+        /*
+         *  Make sure that allocated stuff is only referenced in the
+         *  archived copy of the data.
+         */
+        for (; ct-- > 0; pOD++)  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (pOD->fOptState & OPTST_STACKED) {
+                    tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                    q->optCookie = NULL;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+            {
+                tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                q->optCookie = NULL;
+            }
+            }
+        }
+    }
+}
+
+
+/*=export_func optionRestore
+ *
+ * what:  restore option state from memory copy
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:  Copy back the option state from saved memory.
+ *       The allocated memory is left intact, so this routine can be
+ *       called repeatedly without having to call optionSaveState again.
+ *       If you are restoring a state that was saved before the first call
+ *       to optionProcess(3AO), then you may change the contents of the
+ *       argc/argv parameters to optionProcess.
+ *
+ * err:  If you have not called @code{optionSaveState} before, a diagnostic is
+ *       printed to @code{stderr} and exit is called.
+=*/
+void
+optionRestore( tOptions* pOpts )
+{
+    tOptions* p = (tOptions*)pOpts->pSavedState;
+
+    if (p == NULL) {
+        tCC* pzName = pOpts->pzProgName;
+        if (pzName == NULL) {
+            pzName = pOpts->pzPROGNAME;
+            if (pzName == NULL)
+                pzName = zNil;
+        }
+        fprintf( stderr, zNoState, pzName );
+        exit( EXIT_FAILURE );
+    }
+    memcpy( pOpts, p, sizeof( *p ));
+    memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc ));
+}
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+/*=export_func optionFree
+ *
+ * what:  free allocated option processing memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   AutoOpts sometimes allocates memory and puts pointers to it in the
+ *        option state structures.  This routine deallocates all such memory.
+ *
+ * err:   As long as memory has not been corrupted,
+ *        this routine is always successful.
+=*/
+void
+optionFree( tOptions* pOpts )
+{
+    if (pOpts->pSavedState != NULL) {
+        AGFREE( pOpts->pSavedState );
+        pOpts->pSavedState = NULL;
+    }
+    {
+        tOptDesc* p = pOpts->pOptDesc;
+        int ct = pOpts->optCt;
+        do  {
+            switch (OPTST_GET_ARGTYPE(p->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (  (p->fOptState & OPTST_STACKED)
+                   && (p->optCookie != NULL)) {
+                    AGFREE( p->optCookie );
+                    p->fOptState &= OPTST_PERSISTENT;
+                    if ((p->fOptState & OPTST_INITENABLED) == 0)
+                        p->fOptState |= OPTST_DISABLED;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+                if (p->optCookie != NULL)
+                    optionUnloadNested(p->optCookie);
+                break;
+            }
+
+            p->optCookie = NULL;
+        } while (p++, --ct > 0);
+    }
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/restore.c */
diff --git a/sntp/libopts/save.c b/sntp/libopts/save.c
new file mode 100644 (file)
index 0000000..c7c1294
--- /dev/null
@@ -0,0 +1,499 @@
+
+/*
+ *  save.c  $Id: save.c,v 4.11 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-20 13:49:46 bkorb"
+ *
+ *  This module's routines will take the currently set options and
+ *  store them into an ".rc" file for re-interpretation the next
+ *  time the invoking program is run.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC  zWarn[] = "%s WARNING:  cannot save options - ";
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tCC*
+findDirName( tOptions* pOpts, int* p_free );
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name );
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA );
+/* = = = END-STATIC-FORWARD = = = */
+
+static tCC*
+findDirName( tOptions* pOpts, int* p_free )
+{
+    tCC*  pzDir;
+
+    if (pOpts->specOptIdx.save_opts == 0)
+        return NULL;
+
+    pzDir = pOpts->pOptDesc[ pOpts->specOptIdx.save_opts ].pzLastArg;
+    if ((pzDir != NULL) && (*pzDir != NUL))
+        return pzDir;
+
+    /*
+     *  This function only works if there is a directory where
+     *  we can stash the RC (INI) file.
+     */
+    {
+        tCC* const* papz = pOpts->papzHomeList;
+        if (papz == NULL)
+            return NULL;
+
+        while (papz[1] != NULL) papz++;
+        pzDir = *papz;
+    }
+
+    /*
+     *  IF it does not require deciphering an env value, then just copy it
+     */
+    if (*pzDir != '$')
+        return pzDir;
+
+    {
+        tCC*  pzEndDir = strchr( ++pzDir, '/' );
+        char* pzFileName;
+        char* pzEnv;
+
+        if (pzEndDir != NULL) {
+            char z[ AO_NAME_SIZE ];
+            if ((pzEndDir - pzDir) > AO_NAME_LIMIT )
+                return NULL;
+            strncpy( z, pzDir, (pzEndDir - pzDir) );
+            z[ (pzEndDir - pzDir) ] = NUL;
+            pzEnv = getenv( z );
+        } else {
+
+            /*
+             *  Make sure we can get the env value (after stripping off
+             *  any trailing directory or file names)
+             */
+            pzEnv = getenv( pzDir );
+        }
+
+        if (pzEnv == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNotDef, pzDir );
+            return NULL;
+        }
+
+        if (pzEndDir == NULL)
+            return pzEnv;
+
+        {
+            size_t sz = strlen( pzEnv ) + strlen( pzEndDir ) + 2;
+            pzFileName = (char*)AGALOC( sz, "dir name" );
+        }
+
+        if (pzFileName == NULL)
+            return NULL;
+
+        *p_free = 1;
+        /*
+         *  Glue together the full name into the allocated memory.
+         *  FIXME: We lose track of this memory.
+         */
+        sprintf( pzFileName, "%s/%s", pzEnv, pzEndDir );
+        return pzFileName;
+    }
+}
+
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name )
+{
+    tCC*   pzDir;
+    struct stat stBuf;
+    int    free_dir_name = 0;
+
+    pzDir = findDirName( pOpts, &free_dir_name );
+    if (pzDir == NULL)
+        return NULL;
+
+    /*
+     *  See if we can find the specified directory.  We use a once-only loop
+     *  structure so we can bail out early.
+     */
+    if (stat( pzDir, &stBuf ) != 0) do {
+
+        /*
+         *  IF we could not, check to see if we got a full
+         *  path to a file name that has not been created yet.
+         */
+        if (errno == ENOENT) {
+            char z[MAXPATHLEN];
+
+            /*
+             *  Strip off the last component, stat the remaining string and
+             *  that string must name a directory
+             */
+            char* pzDirCh = strrchr( pzDir, '/' );
+            if (pzDirCh == NULL) {
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+
+            strncpy( z, pzDir, pzDirCh - pzDir );
+            z[ pzDirCh - pzDir ] = NUL;
+
+            if (  (stat( z, &stBuf ) == 0)
+               && S_ISDIR( stBuf.st_mode )) {
+
+                /*
+                 *  We found the directory.  Restore the file name and
+                 *  mark the full name as a regular file
+                 */
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+        }
+
+        /*
+         *  We got a bogus name.
+         */
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNoStat, errno, strerror( errno ), pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    } while (0);
+
+    /*
+     *  IF what we found was a directory,
+     *  THEN tack on the config file name
+     */
+    if (S_ISDIR( stBuf.st_mode )) {
+        size_t sz = strlen( pzDir ) + strlen( pOpts->pzRcName ) + 2;
+
+        {
+            char*  pzPath = (char*)AGALOC( sz, "file name" );
+#ifdef HAVE_SNPRINTF
+            snprintf( pzPath, sz, "%s/%s", pzDir, pOpts->pzRcName );
+#else
+            sprintf( pzPath, "%s/%s", pzDir, pOpts->pzRcName );
+#endif
+            if (free_dir_name)
+                AGFREE( (void*)pzDir );
+            pzDir = pzPath;
+            free_dir_name = 1;
+        }
+
+        /*
+         *  IF we cannot stat the object for any reason other than
+         *     it does not exist, then we bail out
+         */
+        if (stat( pzDir, &stBuf ) != 0) {
+            if (errno != ENOENT) {
+                fprintf( stderr, zWarn, pOpts->pzProgName );
+                fprintf( stderr, zNoStat, errno, strerror( errno ),
+                         pzDir );
+                AGFREE( (void*)pzDir );
+                return NULL;
+            }
+
+            /*
+             *  It does not exist yet, but it will be a regular file
+             */
+            stBuf.st_mode = S_IFREG;
+        }
+    }
+
+    /*
+     *  Make sure that whatever we ultimately found, that it either is
+     *  or will soon be a file.
+     */
+    if (! S_ISREG( stBuf.st_mode )) {
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNotFile, pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    }
+
+    /*
+     *  Get rid of the old file
+     */
+    unlink( pzDir );
+    *p_free_name = free_dir_name;
+    return pzDir;
+}
+
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA )
+{
+    /*
+     *  There is an argument.  Pad the name so values line up
+     */
+    fprintf( fp, "%-18s",
+             (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+
+    /*
+     *  IF the option is numeric only,
+     *  THEN the char pointer is really the number
+     */
+    if (OPTST_GET_ARGTYPE(p->fOptState) == OPARG_TYPE_NUMERIC)
+        fprintf( fp, "  %d\n", (t_word)pzLA );
+
+    /*
+     *  OTHERWISE, FOR each line of the value text, ...
+     */
+    else if (pzLA == NULL)
+        fputc( '\n', fp );
+
+    else {
+        fputc( ' ', fp ); fputc( ' ', fp );
+        for (;;) {
+            tCC* pzNl = strchr( pzLA, '\n' );
+
+            /*
+             *  IF this is the last line
+             *  THEN bail and print it
+             */
+            if (pzNl == NULL)
+                break;
+
+            /*
+             *  Print the continuation and the text from the current line
+             */
+            fwrite( pzLA, pzNl - pzLA, 1, fp );
+            pzLA = pzNl+1; /* advance the Last Arg pointer */
+            fputs( "\\\n", fp );
+        }
+
+        /*
+         *  Terminate the entry
+         */
+        fputs( pzLA, fp );
+        fputc( '\n', fp );
+    }
+}
+
+
+/*=export_func  optionSaveFile
+ *
+ * what:  saves the option state to a file
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ *
+ * doc:
+ *
+ * This routine will save the state of option processing to a file.  The name
+ * of that file can be specified with the argument to the @code{--save-opts}
+ * option, or by appending the @code{rcfile} attribute to the last
+ * @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ * will default to @code{.@i{programname}rc}.  If you wish to specify another
+ * file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ *
+ * err:
+ *
+ * If no @code{homerc} file was specified, this routine will silently return
+ * and do nothing.  If the output file cannot be created or updated, a message
+ * will be printed to @code{stderr} and the routine will return.
+=*/
+void
+optionSaveFile( tOptions* pOpts )
+{
+    tOptDesc* pOD;
+    int       ct;
+    FILE*     fp;
+
+    {
+        int   free_name = 0;
+        tCC*  pzFName = findFileName( pOpts, &free_name );
+        if (pzFName == NULL)
+            return;
+
+        fp = fopen( pzFName, "w" FOPEN_BINARY_FLAG );
+        if (fp == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNoCreat, errno, strerror( errno ), pzFName );
+            if (free_name)
+                AGFREE((void*) pzFName );
+            return;
+        }
+
+        if (free_name)
+            AGFREE( (void*)pzFName );
+    }
+
+    {
+        const char*  pz = pOpts->pzUsageTitle;
+        fputs( "#  ", fp );
+        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
+    }
+
+    {
+        time_t  timeVal = time( NULL );
+        char*   pzTime  = ctime( &timeVal );
+
+        fprintf( fp, zPresetFile, pzTime );
+#ifdef HAVE_ALLOCATED_CTIME
+        /*
+         *  The return values for ctime(), localtime(), and gmtime()
+         *  normally point to static data that is overwritten by each call.
+         *  The test to detect allocated ctime, so we leak the memory.
+         */
+        AGFREE( (void*)pzTime );
+#endif
+    }
+
+    /*
+     *  FOR each of the defined options, ...
+     */
+    ct  = pOpts->presetOptCt;
+    pOD = pOpts->pOptDesc;
+    do  {
+        int arg_state;
+        tOptDesc*  p;
+
+        /*
+         *  IF    the option has not been defined
+         *     OR it does not take an initialization value
+         *     OR it is equivalenced to another option
+         *  THEN continue (ignore it)
+         */
+        if (UNUSED_OPT( pOD ))
+            continue;
+
+        if ((pOD->fOptState & (OPTST_NO_INIT|OPTST_DOCUMENT|OPTST_OMITTED))
+            != 0)
+            continue;
+
+        if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+              && (pOD->optEquivIndex != pOD->optIndex))
+            continue;
+
+        /*
+         *  Set a temporary pointer to the real option description
+         *  (i.e. account for equivalencing)
+         */
+        p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0)
+            ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD;
+
+        /*
+         *  IF    no arguments are allowed
+         *  THEN just print the name and continue
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            fprintf( fp, "%s\n",
+                     (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+            continue;
+        }
+
+        arg_state = OPTST_GET_ARGTYPE(p->fOptState);
+        switch (arg_state) {
+        case 0:
+        case OPARG_TYPE_NUMERIC:
+            printEntry( fp, p, p->pzLastArg );
+            break;
+
+        case OPARG_TYPE_STRING:
+            if (p->fOptState & OPTST_STACKED) {
+                tArgList*  pAL = (tArgList*)p->optCookie;
+                int        uct = pAL->useCt;
+                tCC**      ppz = pAL->apzArgs;
+
+                /*
+                 *  Disallow multiple copies of disabled options.
+                 */
+                if (uct > 1)
+                    p->fOptState &= ~OPTST_DISABLED;
+
+                while (uct-- > 0)
+                    printEntry( fp, p, *(ppz++) );
+            } else {
+                printEntry( fp, p, p->pzLastArg );
+            }
+            break;
+
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+        {
+            tCC* val = p->pzLastArg;
+            /*
+             *  This is a magic incantation that will convert the
+             *  bit flag values back into a string suitable for printing.
+             */
+            (*(p->pOptProc))( (tOptions*)2UL, p );
+            printEntry( fp, p, p->pzLastArg );
+            if ((p->pzLastArg != NULL) && (arg_state != OPARG_TYPE_ENUMERATION))
+                /*
+                 *  bit flag and enumeration strings get allocated
+                 */
+                AGFREE( (void*)p->pzLastArg );
+            p->pzLastArg = val;
+            break;
+        }
+
+        case OPARG_TYPE_BOOLEAN:
+            printEntry( fp, p, (p->pzLastArg != 0) ? "true" : "false" );
+            break;
+
+        default:
+            break; /* cannot handle - skip it */
+        }
+    } while ( (pOD++), (--ct > 0));
+
+    fclose( fp );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/save.c */
diff --git a/sntp/libopts/sort.c b/sntp/libopts/sort.c
new file mode 100644 (file)
index 0000000..64d616a
--- /dev/null
@@ -0,0 +1,369 @@
+
+/*
+ *  sort.c  $Id: sort.c,v 4.6 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-20 17:18:41 bkorb"
+ *
+ *  This module implements argument sorting.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  "mustHandleArg" and "mayHandleArg" are really similar.  The biggest
+ *  difference is that "may" will consume the next argument only if it
+ *  does not start with a hyphen and "must" will consume it, hyphen or not.
+ */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is required.  Long options can either have
+     *  a separate command line argument, or an argument attached by
+     *  the '=' character.  Figure out which.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  See if an arg string follows the flag character.  If not,
+         *  the next arg must be the option argument.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  See if an arg string has already been assigned (glued on
+         *  with an `=' character).  If not, the next is the opt arg.
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return FAILURE;
+
+    ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is optional.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  IF nothing is glued on after the current flag character,
+         *  THEN see if there is another argument.  If so and if it
+         *  does *NOT* start with a hyphen, then it is the option arg.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  Look for an argument if we don't already have one (glued on
+         *  with a `=' character)
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM;
+
+    pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+    if (*pzArg != '-')
+        ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+/*
+ *  Process a string of short options glued together.  If the last one
+ *  does or may take an argument, the do the argument processing and leave.
+ */
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx )
+{
+    while (*pzArg != NUL) {
+        if (FAILED( shortOptionFind( pOpts, *pzArg, pOS )))
+            return FAILURE;
+
+        /*
+         *  See if we can have an arg.
+         */
+        if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArg++;
+
+        } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            /*
+             *  Take an argument if it is not attached and it does not
+             *  start with a hyphen.
+             */
+            if (pzArg[1] != NUL)
+                return SUCCESS;
+
+            pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+            if (*pzArg != '-')
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            return SUCCESS;
+
+        } else {
+            /*
+             *  IF we need another argument, be sure it is there and
+             *  take it.
+             */
+            if (pzArg[1] == NUL) {
+                if (pOpts->curOptIdx >= pOpts->origArgCt)
+                    return FAILURE;
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            }
+            return SUCCESS;
+        }
+    }
+    return SUCCESS;
+}
+
+/*
+ *  If the program wants sorted options (separated operands and options),
+ *  then this routine will to the trick.
+ */
+LOCAL void
+optionSort( tOptions* pOpts )
+{
+    char** ppzOpts;
+    char** ppzOpds;
+    int    optsIdx = 0;
+    int    opdsIdx = 0;
+
+    tOptState os = OPTSTATE_INITIALIZER(DEFINED);
+
+    /*
+     *  Disable for POSIX conformance
+     */
+    if (getenv( "POSIXLY_CORRECT" ) != NULL) {
+        errno = 0;
+        return;
+    }
+
+    errno = ENOENT;
+
+    /*
+     *  If all arguments are named, we can't sort 'em.  There are no operands.
+     */
+    if (NAMED_OPTS(pOpts))
+        return;
+
+    /*
+     *  Make sure we can allocate two full-sized arg vectors.
+     */
+    ppzOpts = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpts == NULL)
+        goto exit_no_mem;
+
+    ppzOpds = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpds == NULL) {
+        free( ppzOpts );
+        goto exit_no_mem;
+    }
+
+    pOpts->curOptIdx = 1;
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        char* pzArg;
+        tSuccess res;
+
+        /*
+         *  If we're out of arguments, we're done.  Join the option and
+         *  operand lists into the original argument vector.
+         */
+        if (pOpts->curOptIdx >= pOpts->origArgCt) {
+            errno = 0;
+            goto joinLists;
+        }
+
+        pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+        if (*pzArg != '-') {
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+        }
+
+        switch (pzArg[1]) {
+        case NUL:
+            /*
+             *  A regular option.  Put it on the operand list.
+             */
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+
+        case '-':
+            /*
+             *  Two consecutive hypens.  Put them on the options list and then
+             *  _always_ force the remainder of the arguments to be operands.
+             */
+            if (pzArg[2] == NUL) {
+                ppzOpts[ optsIdx++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+                goto restOperands;
+            }
+            res = longOptionFind( pOpts, pzArg+2, &os );
+            break;
+
+        default:
+            /*
+             *  If short options are not allowed, then do long
+             *  option processing.  Otherwise the character must be a
+             *  short (i.e. single character) option.
+             */
+            if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) {
+                res = longOptionFind( pOpts, pzArg+1, &os );
+            } else {
+                res = shortOptionFind( pOpts, pzArg[1], &os );
+            }
+            break;
+        }
+        if (FAILED( res )) {
+            errno = EIO;
+            goto freeTemps;
+        }
+
+        /*
+         *  We've found an option.  Add the argument to the option list.
+         *  Next, we have to see if we need to pull another argument to be
+         *  used as the option argument.
+         */
+        ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+        if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
+            /*
+             *  No option argument.  If we have a short option here,
+             *  then scan for short options until we get to the end
+             *  of the argument string.
+             */
+            if (  (os.optType == TOPT_SHORT)
+               && FAILED( checkShortOpts( pOpts, pzArg+2, &os,
+                                          ppzOpts, &optsIdx )) )  {
+                errno = EIO;
+                goto freeTemps;
+            }
+
+        } else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            switch (mayHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case FAILURE: errno = EIO; goto freeTemps;
+            case PROBLEM: errno = 0;   goto joinLists;
+            }
+
+        } else {
+            switch (mustHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case PROBLEM:
+            case FAILURE: errno = EIO; goto freeTemps;
+            }
+        }
+    } /* for (;;) */
+
+ restOperands:
+    while (pOpts->curOptIdx < pOpts->origArgCt)
+        ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+ joinLists:
+    if (optsIdx > 0)
+        memcpy( pOpts->origArgVect + 1, ppzOpts, optsIdx * sizeof( char* ));
+    if (opdsIdx > 0)
+        memcpy( pOpts->origArgVect + 1 + optsIdx,
+                ppzOpds, opdsIdx * sizeof( char* ));
+
+ freeTemps:
+    free( ppzOpts );
+    free( ppzOpds );
+    return;
+
+ exit_no_mem:
+    errno = ENOMEM;
+    return;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/sort.c */
diff --git a/sntp/libopts/stack.c b/sntp/libopts/stack.c
new file mode 100644 (file)
index 0000000..d72b0e9
--- /dev/null
@@ -0,0 +1,224 @@
+
+/*
+ *  stack.c
+ *  $Id: stack.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ *  Time-stamp:      "2005-02-20 16:33:20 bkorb"
+ *
+ *  This is a special option processing routine that will save the
+ *  argument to an option in a FIFO queue.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#include REGEX_HEADER
+
+/*=export_func  optionUnstackArg
+ * private:
+ *
+ * what:  Remove option args from a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Invoked for options that are equivalenced to stacked options.
+=*/
+void
+optionUnstackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOptDesc )
+{
+    int       res;
+
+    tArgList* pAL = (tArgList*)pOptDesc->optCookie;
+    /*
+     *  IF we don't have any stacked options,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL == NULL) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        return;
+    }
+
+    {
+        regex_t   re;
+        int       i, ct, dIdx;
+
+        if (regcomp( &re, pOptDesc->pzLastArg, REG_NOSUB ) != 0)
+            return;
+
+        /*
+         *  search the list for the entry(s) to remove.  Entries that
+         *  are removed are *not* copied into the result.  The source
+         *  index is incremented every time.  The destination only when
+         *  we are keeping a define.
+         */
+        for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
+            tCC*      pzSrc = pAL->apzArgs[ i ];
+            char*     pzEq  = strchr( pzSrc, '=' );
+
+            if (pzEq != NULL)
+                *pzEq = NUL;
+
+            res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
+            switch (res) {
+            case 0:
+                /*
+                 *  Remove this entry by reducing the in-use count
+                 *  and *not* putting the string pointer back into
+                 *  the list.
+                 */
+                pAL->useCt--;
+                break;
+
+            default:
+            case REG_NOMATCH:
+                if (pzEq != NULL)
+                    *pzEq = '=';
+
+                /*
+                 *  IF we have dropped an entry
+                 *  THEN we have to move the current one.
+                 */
+                if (dIdx != i)
+                    pAL->apzArgs[ dIdx ] = pzSrc;
+                dIdx++;
+            }
+        }
+
+        regfree( &re );
+    }
+
+    /*
+     *  IF we have unstacked everything,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL->useCt == 0) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        free( (void*)pAL );
+        pOptDesc->optCookie = NULL;
+    }
+}
+
+
+/*
+ *  Put an entry into an argument list.  The first argument points to
+ *  a pointer to the argument list structure.  It gets passed around
+ *  as an opaque address.
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry )
+{
+    tArgList* pAL = *(void**)ppAL;
+
+    /*
+     *  IF we have never allocated one of these,
+     *  THEN allocate one now
+     */
+    if (pAL == NULL) {
+        pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
+        if (pAL == NULL)
+            return;
+        pAL->useCt   = 0;
+        pAL->allocCt = MIN_ARG_ALLOC_CT;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  ELSE if we are out of room
+     *  THEN make it bigger
+     */
+    else if (pAL->useCt >= pAL->allocCt) {
+        size_t sz = sizeof( *pAL );
+        pAL->allocCt += INCR_ARG_ALLOC_CT;
+
+        /*
+         *  The base structure contains space for MIN_ARG_ALLOC_CT
+         *  pointers.  We subtract it off to find our augment size.
+         */
+        sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
+        pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
+        if (pAL == NULL)
+            return;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  Insert the new argument into the list
+     */
+    pAL->apzArgs[ (pAL->useCt)++ ] = entry;
+}
+
+
+/*=export_func  optionStackArg
+ * private:
+ *
+ * what:  put option args on a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Keep an entry-ordered list of option arguments.
+=*/
+void
+optionStackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOD )
+{
+    if (pOD->pzLastArg == NULL)
+        return;
+
+    addArgListEntry( &(pOD->optCookie), (void*)pOD->pzLastArg );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/stack.c */
diff --git a/sntp/libopts/streqvcmp.c b/sntp/libopts/streqvcmp.c
new file mode 100644 (file)
index 0000000..e9f638d
--- /dev/null
@@ -0,0 +1,292 @@
+
+/*
+ *  $Id: streqvcmp.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-04-10 14:05:53 bkorb"
+ *
+ *  String Equivalence Comparison
+ *
+ *  These routines allow any character to be mapped to any other
+ *  character before comparison.  In processing long option names,
+ *  the characters "-", "_" and "^" all need to be equivalent
+ *  (because they are treated so by different development environments).
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
+    '\b', '\t', '\n', '\v',  '\f', '\r', 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
+
+    ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
+
+    '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
+    '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
+
+    0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
+    0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
+    0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
+    0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
+    0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
+    0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
+
+    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
+    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
+    0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
+    0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
+    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
+    0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
+    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
+    0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+
+/*=export_func strneqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + tCC* + str1 + first string +
+ * arg:  + tCC* + str2 + second string +
+ * arg:  + int  + ct   + compare length +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * The comparison is limited to @code{ct} bytes.
+ * This function name is mapped to option_strneqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+strneqvcmp( tCC* s1, tCC* s2, int ct )
+{
+    for (; ct > 0; --ct) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+
+    return 0;
+}
+
+
+/*=export_func streqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + const char* + str1 + first string +
+ * arg:  + const char* + str2 + second string +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * This function name is mapped to option_streqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+streqvcmp( tCC* s1, tCC* s2 )
+{
+    for (;;) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+}
+
+
+/*=export_func streqvmap
+ *
+ * what: Set the character mappings for the streqv functions
+ *
+ * arg:  + char + From + Input character +
+ * arg:  + char + To   + Mapped-to character +
+ * arg:  + int  + ct   + compare length +
+ *
+ * doc:
+ *
+ * Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ * the map is cleared by setting all entries in the map to their index
+ * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ * are incremented and the process repeated until @code{ct} entries have been
+ * set. For example,
+ * @example
+ *    streqvmap( 'a', 'A', 26 );
+ * @end example
+ * @noindent
+ * will alter the mapping so that all English lower case letters
+ * will map to upper case.
+ *
+ * This function name is mapped to option_streqvmap so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+streqvmap( char From, char To, int ct )
+{
+    if (ct == 0) {
+        ct = sizeof( charmap ) - 1;
+        do  {
+            charmap[ ct ] = ct;
+        } while (--ct >= 0);
+    }
+
+    else {
+        int  chTo   = (int)To   & 0xFF;
+        int  chFrom = (int)From & 0xFF;
+
+        do  {
+            charmap[ chFrom ] = (unsigned)chTo;
+            chFrom++;
+            chTo++;
+            if ((chFrom >= sizeof( charmap )) || (chTo >= sizeof( charmap )))
+                break;
+        } while (--ct > 0);
+    }
+}
+
+
+/*=export_func strequate
+ *
+ * what: map a list of characters to the same value
+ *
+ * arg:  + const char* + ch_list + characters to equivalence +
+ *
+ * doc:
+ *
+ * Each character in the input string get mapped to the first character
+ * in the string.
+ * This function name is mapped to option_strequate so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strequate( const char* s )
+{
+    if ((s != NULL) && (*s != NUL)) {
+        unsigned char equiv = (unsigned)*s;
+        while (*s != NUL)
+            charmap[ (unsigned)*(s++) ] = equiv;
+    }
+}
+
+
+/*=export_func strtransform
+ *
+ * what: convert a string into its mapped-to value
+ *
+ * arg:  + char*       + dest + output string +
+ * arg:  + const char* + src  + input string +
+ *
+ * doc:
+ *
+ * Each character in the input string is mapped and the mapped-to
+ * character is put into the output.
+ * This function name is mapped to option_strtransform so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strtransform( d, s )
+    char*       d;
+    const char* s;
+{
+    do  {
+        *(d++) = (char)charmap[ (unsigned)*s ];
+    } while (*(s++) != NUL);
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/streqvcmp.c */
diff --git a/sntp/libopts/text_mmap.c b/sntp/libopts/text_mmap.c
new file mode 100644 (file)
index 0000000..abdcf42
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * $Id: text_mmap.c,v 4.5 2005/04/16 17:07:29 bkorb Exp $
+ *
+ * Time-stamp:      "2005-02-24 11:56:43 bkorb"
+ */
+
+#define FILE_WRITABLE(_prt,_flg) \
+       ((_prt & PROT_WRITE) && (_flg & (MAP_SHARED|MAP_PRIVATE) == MAP_SHARED))
+
+/***export_func  text_mmap
+ *
+ * what:  map a text file with terminating NUL
+ *
+ * arg:   const char*,  pzFile,  name of the file to map
+ * arg:   int,          prot,    mmap protections (see mmap(2))
+ * arg:   int,          flags,   mmap flags (see mmap(2))
+ * arg:   tmap_info_t*, mapinfo, returned info about the mapping
+ *
+ * ret-type:   void*
+ * ret-desc:   The mmaped data address
+ *
+ * doc:
+ *
+ * This routine will mmap a file into memory ensuring that there is at least
+ * one @file{NUL} character following the file data.  It will return the
+ * address where the file contents have been mapped into memory.  If there is a
+ * problem, then it will return @code{MAP_FAILED} and set @file{errno}
+ * appropriately.
+ *
+ * The named file does not exist, @code{stat(2)} will set @file{errno} as it
+ * will.  If the file is not a regular file, @file{errno} will be
+ * @code{EINVAL}.  At that point, @code{open(2)} is attempted with the access
+ * bits set appropriately for the requested @code{mmap(2)} protections and flag
+ * bits.  On failure, @file{errno} will be set according to the documentation
+ * for @code{open(2)}.  If @code{mmap(2)} fails, @file{errno} will be set as
+ * that routine sets it.  If @code{text_mmap} works to this point, a valid
+ * address will be returned, but there may still be ``issues''.
+ *
+ * If the file size is not an even multiple of the system page size, then
+ * @code{text_map} will return at this point and @file{errno} will be zero.
+ * Otherwise, an anonymous map is attempted.  If not available, then an attempt
+ * is made to @code{mmap(2)} @file{/dev/zero}.  If any of these fail, the
+ * address of the file's data is returned, bug @code{no} @file{NUL} characters
+ * are mapped after the end of the data.
+ *
+ * see: mmap(2), open(2), stat(2)
+ *
+ * err: Any error code issued by mmap(2), open(2), stat(2) is possible.
+ *      Additionally, if the specified file is not a regular file, then
+ *      errno will be set to @code{EINVAL}.
+ *
+ * example:
+ * #include <mylib.h>
+ * tmap_info_t mi;
+ * int no_nul;
+ * void* data = text_mmap( "file", PROT_WRITE, MAP_PRIVATE, &mi );
+ * if (data == MAP_FAILED) return;
+ * no_nul = (mi.txt_size == mi.txt_full_size);
+ * << use the data >>
+ * text_munmap( &mi );
+=*/
+LOCAL void*
+text_mmap( const char* pzFile, int prot, int flags, tmap_info_t* pMI )
+{
+    memset( pMI, 0, sizeof(*pMI) );
+#ifdef HAVE_MMAP
+    pMI->txt_zero_fd = -1;
+#endif
+    pMI->txt_fd = -1;
+
+    /*
+     *  Make sure we can stat the regular file.  Save the file size.
+     */
+    {
+        struct stat sb;
+        if (stat( pzFile, &sb ) != 0) {
+            pMI->txt_errno = errno;
+            return MAP_FAILED;
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            pMI->txt_errno = errno = EINVAL;
+            return MAP_FAILED;
+        }
+
+        pMI->txt_size = sb.st_size;
+    }
+
+    /*
+     *  Map mmap flags and protections into open flags and do the open.
+     */
+    {
+        int o_flag;
+        /*
+         *  See if we will be updating the file.  If we can alter the memory
+         *  and if we share the data and we are *not* copy-on-writing the data,
+         *  then our updates will show in the file, so we must open with
+         *  write access.
+         */
+        if (FILE_WRITABLE(prot,flags))
+            o_flag = O_RDWR;
+        else
+            o_flag = O_RDONLY;
+
+        /*
+         *  If you're not sharing the file and you are writing to it,
+         *  then don't let anyone else have access to the file.
+         */
+        if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE))
+            o_flag |= O_EXCL;
+
+        pMI->txt_fd = open( pzFile, o_flag );
+    }
+
+    if (pMI->txt_fd < 0) {
+        pMI->txt_errno = errno;
+        return MAP_FAILED;
+    }
+
+#ifdef HAVE_MMAP /* * * * * WITH MMAP * * * * * */
+    /*
+     *  do the mmap.  If we fail, then preserve errno, close the file and
+     *  return the failure.
+     */
+    pMI->txt_data = mmap( NULL, pMI->txt_size, prot, flags, pMI->txt_fd, 0 );
+    if (pMI->txt_data == MAP_FAILED) {
+        pMI->txt_errno = errno;
+        goto fail_return;
+    }
+
+    /*
+     *  Most likely, everything will turn out fine now.  The only difficult
+     *  part at this point is coping with files with sizes that are a multiple
+     *  of the page size.  Handling that is what this whole thing is about.
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    do {
+#ifdef _SC_PAGESIZE
+        size_t pgsz = sysconf(_SC_PAGESIZE);
+#else
+        size_t pgsz = getpagesize();
+#endif
+        /*
+         *  Compute the pagesize rounded mapped memory size.
+         *  IF this is not the same as the file size, then there are NUL's
+         *  at the end of the file mapping and all is okay.
+         */
+        pMI->txt_full_size = (pMI->txt_size + (pgsz - 1)) & ~(pgsz - 1);
+        if (pMI->txt_size != pMI->txt_full_size)
+            break;
+
+        /*
+         *  Still here?  We have to append a page of NUL's
+         */
+        pMI->txt_full_size += pgsz;
+        {
+#ifdef MAP_ANONYMOUS
+            void* pNuls = mmap(
+                (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
+                PROT_READ, MAP_ANONYMOUS|MAP_FIXED, 0, 0 );
+
+            if (pNuls == MAP_FAILED) {
+                pMI->txt_errno = errno;
+                pMI->txt_full_size = pMI->txt_size;
+            }
+#else
+            pMI->txt_zero_fd = open( "/dev/zero", O_RDONLY );
+
+            if (pMI->txt_zero_fd < 0) {
+                pMI->txt_errno = errno;
+                pMI->txt_full_size = pMI->txt_size;
+
+            } else {
+                void* pNuls = mmap(
+                    (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
+                    PROT_READ, MAP_PRIVATE|MAP_FIXED, pMI->txt_zero_fd, 0 );
+
+                if (pNuls == MAP_FAILED) {
+                    pMI->txt_errno = errno;
+                    close( pMI->txt_zero_fd );
+                    pMI->txt_zero_fd = -1;
+                }
+            }
+#endif
+        }
+    } while(0);
+
+    return pMI->txt_data;
+
+#else /* * * * * * no HAVE_MMAP * * * * * */
+
+    pMI->txt_data = AGALOC( pMI->txt_size+1, "file text" );
+    if (pMI->txt_data == NULL) {
+        pMI->txt_errno = ENOMEM;
+        goto fail_return;
+    }
+
+    {
+        size_t sz = pMI->txt_size;
+        char*  pz = pMI->txt_data;
+
+        while (sz > 0) {
+            ssize_t rdct = read( pMI->txt_fd, pz, sz );
+            if (rdct <= 0) {
+                pMI->txt_errno = errno;
+                fprintf( stderr, zFSErrReadFile,
+                         errno, strerror( errno ), pzFile );
+                free( pMI->txt_data );
+                goto fail_return;
+            }
+
+            pz += rdct;
+            sz -= rdct;
+        }
+
+        *pz = NUL;
+    }
+
+    /*
+     *  We never need a dummy page mapped in
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    return pMI->txt_data;
+
+#endif /* * * * * * no HAVE_MMAP * * * * * */
+
+ fail_return:
+    if (pMI->txt_fd >= 0) {
+        close( pMI->txt_fd );
+        pMI->txt_fd = -1;
+    }
+    errno = pMI->txt_errno;
+    pMI->txt_data = MAP_FAILED;
+    return pMI->txt_data;
+}
+
+
+/***export_func  text_munmap
+ *
+ * what:  unmap the data mapped in by text_mmap
+ *
+ * arg:   tmap_info_t*, mapinfo, info about the mapping
+ *
+ * ret-type:   int
+ * ret-desc:   -1 or 0.  @file{errno} will have the error code.
+ *
+ * doc:
+ *
+ * This routine will unmap the data mapped in with @code{text_mmap} and close
+ * the associated file descriptors opened by that function.
+ *
+ * see: munmap(2), close(2)
+ *
+ * err: Any error code issued by munmap(2) or close(2) is possible.
+=*/
+LOCAL int
+text_munmap( tmap_info_t* pMI )
+{
+#ifdef HAVE_MMAP
+    int res = munmap( pMI->txt_data, pMI->txt_full_size );
+    if (res != 0)
+        goto error_return;
+
+    res = close( pMI->txt_fd );
+    if (res != 0)
+        goto error_return;
+
+    pMI->txt_fd = -1;
+    errno = 0;
+    if (pMI->txt_zero_fd != -1) {
+        res = close( pMI->txt_zero_fd );
+        if (res == 0)
+            pMI->txt_zero_fd = -1;
+    }
+
+ error_return:
+    pMI->txt_errno = errno;
+    return res;
+#else  /* HAVE_MMAP */
+
+    errno = 0;
+    /*
+     *  IF the memory is writable *AND* it is not private (copy-on-write)
+     *     *AND* the memory is "sharable" (seen by other processes)
+     *  THEN rewrite the data.
+     */
+    if (   FILE_WRITABLE(pMI->txt_prot, pMI->txt_flags)
+        && (lseek( pMI->txt_fd, 0, SEEK_SET ) >= 0) ) {
+        write( pMI->txt_fd, pMI->txt_data, pMI->txt_size );
+    }
+
+    close( pMI->txt_fd );
+    pMI->txt_fd = -1;
+    pMI->txt_errno = errno;
+    free( pMI->txt_data );
+
+    return pMI->txt_errno;
+#endif /* HAVE_MMAP */
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/text_mmap.c */
diff --git a/sntp/libopts/tokenize.c b/sntp/libopts/tokenize.c
new file mode 100644 (file)
index 0000000..074473c
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *  This file defines the string_tokenize interface
+ * Time-stamp:      "2005-04-25 18:47:21 bkorb"
+ *
+ *  string_tokenize copyright 2005 Bruce Korb
+ *
+ *  string_tokenize is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  string_tokenize 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with string_tokenize; if not, write to:
+ *             The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#define cc_t   const unsigned char
+#define ch_t   unsigned char
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc );
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = (ch_t*)*ppDest;
+    const ch_t* pSrc  = (const ch_t*)(*ppSrc + 1);
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '"':   goto done;
+        case '\\':
+            pSrc += ao_string_cook_escape_char( (char*)pSrc, (char*)&ch, 0x7F );
+            if (ch == 0x7F)
+                break;
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = (ch_t*)pDest; /* next spot for storing character */
+    *ppSrc  = (ch_t*)pSrc;  /* char following closing quote    */
+}
+
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = *ppDest;
+    cc_t* pSrc  = *ppSrc + 1;
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '\'':  goto done;
+        case '\\':
+            /*
+             *  *Four* escapes are handled:  newline removal, escape char
+             *  quoting and apostrophe quoting
+             */
+            switch (*pSrc) {
+            case NUL:   *ppSrc = NULL; return;
+            case '\r':
+                if (*(++pSrc) == '\n')
+                    ++pSrc;
+                continue;
+
+            case '\n':
+                ++pSrc;
+                continue;
+
+            case '\'':
+                ch = '\'';
+                /* FALLTHROUGH */
+
+            case '\\':
+                ++pSrc;
+                break;
+            }
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = pDest; /* next spot for storing character */
+    *ppSrc  = pSrc;  /* char following closing quote    */
+}
+
+
+/*=export_func ao_string_tokenize
+ *
+ * what: tokenize an input string
+ *
+ * arg:  + const char* + string + string to be tokenized +
+ *
+ * ret_type:  token_list_t*
+ * ret_desc:  pointer to a structure that lists each token
+ *
+ * doc:
+ *
+ * This function will convert one input string into a list of strings.
+ * The list of strings is derived by separating the input based on
+ * white space separation.  However, if the input contains either single
+ * or double quote characters, then the text after that character up to
+ * a matching quote will become the string in the list.
+ *
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *
+ * There are two types of quoted strings: single quoted (@code{'}) and
+ * double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ * escape characters (@code{\\}) are simply another character, except when
+ * preceding the following characters:
+ * @example
+ * @code{\\}  double backslashes reduce to one
+ * @code{'}   incorporates the single quote into the string
+ * @code{\n}  suppresses both the backslash and newline character
+ * @end example
+ *
+ * Double quote strings are formed according to the rules of string
+ * constants in ANSI-C programs.
+ *
+ * example:
+ * @example
+ *    #include <stdlib.h>
+ *    int ix;
+ *    token_list_t* ptl = ao_string_tokenize( some_string )
+ *    for (ix = 0; ix < ptl->tkn_ct; ix++)
+ *       do_something_with_tkn( ptl->tkn_list[ix] );
+ *    free( ptl );
+ * @end example
+ * Note that everything is freed with the one call to @code{free(3C)}.
+ *
+ * err:
+ *  NULL is returned and @code{errno} will be set to indicate the problem:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - There was an unterminated quoted string.
+ *  @item
+ *  @code{ENOENT} - The input string was empty.
+ *  @item
+ *  @code{ENOMEM} - There is not enough memory.
+ *  @end itemize
+=*/
+token_list_t*
+ao_string_tokenize( const char* str )
+{
+    int max_token_ct = 1; /* allow for trailing NUL on string */
+    token_list_t* res;
+
+    if (str == NULL)  goto bogus_str;
+
+    /*
+     *  Trim leading white space.  Use "ENOENT" and a NULL return to indicate
+     *  an empty string was passed.
+     */
+    while (isspace( *str ))  str++;
+    if (*str == NUL) {
+    bogus_str:
+        errno = ENOENT;
+        return NULL;
+    }
+
+    /*
+     *  Take an approximate count of tokens.  If no quoted strings are used,
+     *  it will be accurate.  If quoted strings are used, it will be a little
+     *  high and we'll squander the space for a few extra pointers.
+     */
+    {
+        cc_t* pz = (cc_t*)str;
+
+        do {
+            max_token_ct++;
+            while (! isspace( *++pz ))
+                if (*pz == NUL) goto found_nul;
+            while (isspace( *pz ))  pz++;
+        } while (*pz != NUL);
+
+    found_nul:
+        ;
+    }
+
+    res = malloc( sizeof(*res) + strlen(str) + (max_token_ct * sizeof(ch_t*)) );
+    if (res == NULL) {
+        errno = ENOMEM;
+        return res;
+    }
+
+    /*
+     *  Now copy each token into the output buffer.
+     */
+    {
+        ch_t* pzDest = (ch_t*)(res->tkn_list + (max_token_ct + 1));
+        res->tkn_ct  = 0;
+
+        do  {
+            res->tkn_list[ res->tkn_ct++ ] = pzDest;
+            for (;;) {
+                char ch = *str;
+                if (isspace( ch )) {
+                found_white_space:
+                    while (isspace( *++str ))  ;
+                    break;
+                }
+
+                switch (ch) {
+                case '"':
+                    copy_cooked( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case '\'':
+                    copy_raw( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case NUL:
+                    goto copy_done;
+
+                default:
+                    str++;
+                    *(pzDest++) = ch;
+                }
+            } copy_done:;
+
+            /*
+             * NUL terminate the last token and see if we have any more tokens.
+             */
+            *(pzDest++) = NUL;
+        } while (*str != NUL);
+
+        res->tkn_list[ res->tkn_ct ] = NULL;
+    }
+
+    return res;
+}
+
+#ifdef TEST
+#include <stdio.h>
+#include <string.h>
+
+int
+main( int argc, char** argv )
+{
+    if (argc == 1) {
+        printf("USAGE:  %s arg [ ... ]\n", *argv);
+        return 1;
+    }
+    while (--argc > 0) {
+        char* arg = *(++argv);
+        token_list_t* p = ao_string_tokenize( arg );
+        if (p == NULL) {
+            printf( "Parsing string ``%s'' failed:\n\terrno %d (%s)\n",
+                    arg, errno, strerror( errno ));
+        } else {
+            int ix = 0;
+            printf( "Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct );
+            do {
+                printf( " %3d:  ``%s''\n", ix+1, p->tkn_list[ix] );
+            } while (++ix < p->tkn_ct);
+            free(p);
+        }
+    }
+    return 0;
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/tokenize.c */
diff --git a/sntp/libopts/usage.c b/sntp/libopts/usage.c
new file mode 100644 (file)
index 0000000..8c9843a
--- /dev/null
@@ -0,0 +1,651 @@
+
+/*
+ *  usage.c  $Id: usage.c,v 4.8 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-20 13:47:52 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ */
+
+/*
+ *  Automated Options copyright 1992-2005 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
+
+#ifndef tSC
+#  define tSC static char
+#endif
+
+static arg_types_t argTypes;
+
+FILE* option_usage_fp = NULL;
+static char    zOptFmtLine[ 16 ];
+static ag_bool displayEnum;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+printProgramDetails( tOptions* pOptions );
+
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+printBareUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+setStdOptFmts( tOptions* pOpts, tCC** ppT );
+
+static void
+setGnuOptFmts( tOptions* pOpts, tCC** ppT );
+
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionUsage
+ * private:
+ *
+ * what:  Print usage text
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + int       + exitCode + exit code for calling exit(3) +
+ *
+ * doc:
+ *  This routine will print usage in both GNU-standard and AutoOpts-expanded
+ *  formats.  The descriptor specifies the default, but AUTOOPTS_USAGE will
+ *  over-ride this, providing the value of it is set to either "gnu" or
+ *  "autoopts".  This routine will @strong{not} return.
+=*/
+void
+optionUsage(
+    tOptions* pOptions,
+    int       exitCode )
+{
+    tCC*    pOptTitle;
+
+    displayEnum = AG_FALSE;
+
+    /*
+     *  Paged usage will preset option_usage_fp to an output file.
+     *  If it hasn't already been set, then set it to standard output
+     *  on successful exit (help was requested), otherwise error out.
+     */
+    if (option_usage_fp == NULL)
+        option_usage_fp = (exitCode != EXIT_SUCCESS) ? stderr : stdout;
+
+    fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName );
+
+    do {
+        char* pz = getenv( "AUTOOPTS_USAGE" );
+        if (pz == NULL) break;
+        if (streqvcmp( pz, "gnu" ) == 0) {
+            pOptions->fOptSet |= OPTPROC_GNUUSAGE;
+            break;
+        }
+        if (streqvcmp( pz, "autoopts" ) == 0) {
+            pOptions->fOptSet &= ~OPTPROC_GNUUSAGE;
+            break;
+        }
+    } while (0);
+
+    /*
+     *  Determine which header and which option formatting strings to use
+     */
+    if ((pOptions->fOptSet & OPTPROC_GNUUSAGE) != 0) {
+        setGnuOptFmts( pOptions, &pOptTitle );
+        fputc( '\n', option_usage_fp );
+    }
+    else {
+        setStdOptFmts( pOptions, &pOptTitle );
+
+        /*
+         *  When we exit with EXIT_SUCCESS and the first option is a doc option,
+         *  we do *NOT* want to emit the column headers.  Otherwise, we do.
+         */
+        if (  (exitCode != EXIT_SUCCESS)
+           || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
+
+            fputs( pOptTitle, option_usage_fp );
+    }
+
+    {
+        int        ct     = pOptions->optCt;
+        int        optNo  = 0;
+        tOptDesc*  pOD    = pOptions->pOptDesc;
+        int        docCt  = 0;
+
+        do  {
+            if ((pOD->fOptState & OPTST_OMITTED) != 0)
+                continue;
+
+            if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
+                if (exitCode == EXIT_SUCCESS) {
+                    fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
+                            pOptTitle);
+                    docCt++;
+                }
+
+                continue;
+            }
+
+            /*
+             *  IF       this is the first auto-opt maintained option
+             *    *AND*  we are doing a full help
+             *    *AND*  there are documentation options
+             *    *AND*  the last one was not a doc option,
+             *  THEN document that the remaining options are not user opts
+             */
+            if (  (pOptions->presetOptCt == optNo)
+               && (exitCode == EXIT_SUCCESS)
+               && (docCt > 0)
+               && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
+                fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle );
+
+            printBareUsage( pOptions, pOD, &argTypes );
+
+            /*
+             *  IF we were invoked because of the --help option,
+             *  THEN print all the extra info
+             */
+            if (exitCode == EXIT_SUCCESS)
+                printExtendedUsage( pOptions, pOD, &argTypes );
+
+        }  while (pOD++, optNo++, (--ct > 0));
+    }
+
+    fputc( '\n', option_usage_fp );
+
+    /*
+     *  Describe the mechanics of denoting the options
+     */
+    switch (pOptions->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:     fputs( zFlagOkay, option_usage_fp ); break;
+    case OPTPROC_SHORTOPT:  break;
+    case OPTPROC_LONGOPT:   fputs( zNoFlags,  option_usage_fp ); break;
+    case 0:                 fputs( zOptsOnly, option_usage_fp ); break;
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) {
+        fputs( zNumberOpt, option_usage_fp );
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) {
+        fputs( zReorder, option_usage_fp );
+    }
+
+    if (pOptions->pzExplain != NULL)
+        fputs( pOptions->pzExplain, option_usage_fp );
+
+    /*
+     *  IF the user is asking for help (thus exiting with SUCCESS),
+     *  THEN see what additional information we can provide.
+     */
+    if (exitCode == EXIT_SUCCESS)
+        printProgramDetails( pOptions );
+
+    if (pOptions->pzBugAddr != NULL)
+        fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr );
+    fflush( option_usage_fp );
+
+    exit( exitCode );
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PROGRAM DETAILS
+ */
+static void
+printProgramDetails( tOptions* pOptions )
+{
+    ag_bool  initIntro = AG_TRUE;
+
+    /*
+     *  Display all the places we look for config files
+     */
+    printInitList( pOptions->papzHomeList, &initIntro,
+                   pOptions->pzRcName, pOptions->pzProgPath );
+
+    /*
+     *  Let the user know about environment variable settings
+     */
+    if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
+        if (initIntro)
+            fputs( zPresetIntro, option_usage_fp );
+
+        fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME );
+    }
+
+    /*
+     *  IF we found an enumeration,
+     *  THEN hunt for it again.  Call the handler proc with a NULL
+     *       option struct pointer.  That tells it to display the keywords.
+     */
+    if (displayEnum) {
+        int        ct     = pOptions->optCt;
+        int        optNo  = 0;
+        tOptDesc*  pOD    = pOptions->pOptDesc;
+
+        fputc( '\n', option_usage_fp );
+        fflush( option_usage_fp );
+        do  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_ENUMERATION:
+            case OPARG_TYPE_MEMBERSHIP:
+                (*(pOD->pOptProc))( NULL, pOD );
+            }
+        }  while (pOD++, optNo++, (--ct > 0));
+    }
+
+    /*
+     *  If there is a detail string, now is the time for that.
+     */
+    if (pOptions->pzDetail != NULL)
+        fputs( pOptions->pzDetail, option_usage_fp );
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PER OPTION TYPE USAGE INFORMATION
+ */
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  IF there are option conflicts or dependencies,
+     *  THEN print them here.
+     */
+    if (  (pOD->pOptMust != NULL)
+       || (pOD->pOptCant != NULL) ) {
+
+        fputs( zTabHyp, option_usage_fp );
+
+        /*
+         *  DEPENDENCIES:
+         */
+        if (pOD->pOptMust != NULL) {
+            const int* pOptNo = pOD->pOptMust;
+
+            fputs( zReqThese, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pOD->pOptCant != NULL)
+                fputs( zTabHypAnd, option_usage_fp );
+        }
+
+        /*
+         *  CONFLICTS:
+         */
+        if (pOD->pOptCant != NULL) {
+            const int* pOptNo = pOD->pOptCant;
+
+            fputs( zProhib, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+        }
+    }
+
+    /*
+     *  IF there is a disablement string
+     *  THEN print the disablement info
+     */
+    if (pOD->pz_DisableName != NULL )
+        fprintf( option_usage_fp, zDis, pOD->pz_DisableName );
+
+    /*
+     *  IF the numeric option has a special callback,
+     *  THEN call it, requesting the range or other special info
+     */
+    if (  (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+       && (pOD->pOptProc != NULL)
+       && (pOD->pOptProc != optionNumericVal) ) {
+        (*(pOD->pOptProc))( pOptions, NULL );
+    }
+
+    /*
+     *  IF the option defaults to being enabled,
+     *  THEN print that out
+     */
+    if (pOD->fOptState & OPTST_INITENABLED)
+        fputs( zEnab, option_usage_fp );
+
+    /*
+     *  IF  the option is in an equivalence class
+     *        AND not the designated lead
+     *  THEN print equivalence and leave it at that.
+     */
+    if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+       && (pOD->optEquivIndex != pOD->optActualIndex )  )  {
+        fprintf( option_usage_fp, zAlt,
+                 pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name );
+        return;
+    }
+
+    /*
+     *  IF this particular option can NOT be preset
+     *    AND some form of presetting IS allowed,
+     *  THEN advise that this option may not be preset.
+     */
+    if (  ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       && (  (pOptions->papzHomeList != NULL)
+          || (pOptions->pzPROGNAME != NULL)
+       )  )
+
+        fputs( zNoPreset, option_usage_fp );
+
+    /*
+     *  Print the appearance requirements.
+     */
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zMembers, option_usage_fp );
+
+    else switch (pOD->optMinCt) {
+    case 1:
+    case 0:
+        switch (pOD->optMaxCt) {
+        case 0:       fputs( zPreset, option_usage_fp ); break;
+        case NOLIMIT: fputs( zNoLim, option_usage_fp );  break;
+        case 1:       break;
+            /*
+             * IF the max is more than one but limited, print "UP TO" message
+             */
+        default:      fprintf( option_usage_fp, zUpTo, pOD->optMaxCt );  break;
+        }
+        break;
+
+    default:
+        /*
+         *  More than one is required.  Print the range.
+         */
+        fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt );
+    }
+
+    if (  NAMED_OPTS( pOptions )
+       && (pOptions->specOptIdx.default_opt == pOD->optIndex))
+        fputs( zDefaultOpt, option_usage_fp );
+}
+
+
+static void
+printBareUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  Flag prefix: IF no flags at all, then omit it.  If not printable
+     *  (not allowed for this option), then blank, else print it.
+     *  Follow it with a comma if we are doing GNU usage and long
+     *  opts are to be printed too.
+     */
+    if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
+        fputs( pAT->pzSpc, option_usage_fp );
+    else if (! isgraph( pOD->optValue)) {
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputc( ' ', option_usage_fp );
+        fputs( pAT->pzNoF, option_usage_fp );
+    } else {
+        fprintf( option_usage_fp, "   -%c", pOD->optValue );
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputs( ", ", option_usage_fp );
+    }
+
+    {
+        char  z[ 80 ];
+        tCC*  pzArgType;
+        /*
+         *  Determine the argument type string first on its usage, then,
+         *  when the option argument is required, base the type string on the
+         *  argument type.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArgType = pAT->pzNo;
+
+        } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            pzArgType = pAT->pzOpt;
+
+        } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey;  break;
+        case OPARG_TYPE_MEMBERSHIP:  pzArgType = pAT->pzKeyL; break;
+        case OPARG_TYPE_BOOLEAN:     pzArgType = pAT->pzBool; break;
+        case OPARG_TYPE_NUMERIC:     pzArgType = pAT->pzNum;  break;
+        case OPARG_TYPE_HIERARCHY:   pzArgType = pAT->pzNest; break;
+        case OPARG_TYPE_STRING:      pzArgType = pAT->pzStr;  break;
+        default:                     goto bogus_desc;         break;
+        }
+
+        snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
+                  (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt );
+
+        fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText );
+
+        switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+            displayEnum |= (pOD->pOptProc != NULL) ? AG_TRUE : AG_FALSE;
+        }
+    }
+    return;
+
+ bogus_desc:
+    fprintf( stderr, zInvalOptDesc, pOD->pz_Name );
+    exit( EXIT_FAILURE );
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   OPTION LINE FORMATTING SETUP
+ *
+ *  The "OptFmt" formats receive three arguments:
+ *  1.  the type of the option's argument
+ *  2.  the long name of the option
+ *  3.  "YES" or "no ", depending on whether or not the option must appear
+ *      on the command line.
+ *  These formats are used immediately after the option flag (if used) has
+ *  been printed.
+ */
+static void
+setStdOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 0;
+
+    argTypes.pzStr  = zStdStrArg;
+    argTypes.pzReq  = zStdReqArg;
+    argTypes.pzNum  = zStdNumArg;
+    argTypes.pzKey  = zStdKeyArg;
+    argTypes.pzKeyL = zStdKeyLArg;
+    argTypes.pzBool = zStdBoolArg;
+    argTypes.pzNest = zStdNestArg;
+    argTypes.pzOpt  = zStdOptArg;
+    argTypes.pzNo   = zStdNoArg;
+    argTypes.pzBrk  = zStdBreak;
+    argTypes.pzNoF  = zFiveSpaces;
+    argTypes.pzSpc  = zTwoSpaces;
+
+    switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
+    case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
+        *ppT = zNoRq_ShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_NO_REQ_OPT:
+        *ppT = zNoRq_NoShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_SHORTOPT:
+        *ppT = zReq_ShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+        break;
+
+    case 0:
+        *ppT = zReq_NoShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+    }
+
+    sprintf( zOptFmtLine, zFmtFmt, flen );
+}
+
+static void
+setGnuOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 22;
+    *ppT = zNoRq_ShrtTtl;
+
+    argTypes.pzStr  = zGnuStrArg;
+    argTypes.pzReq  = zOneSpace;
+    argTypes.pzNum  = zGnuNumArg;
+    argTypes.pzKey  = zGnuKeyArg;
+    argTypes.pzKeyL = zGnuKeyLArg;
+    argTypes.pzBool = zGnuBoolArg;
+    argTypes.pzNest = zGnuNestArg;
+    argTypes.pzOpt  = zGnuOptArg;
+    argTypes.pzNo   = zOneSpace;
+    argTypes.pzBrk  = zGnuBreak;
+    argTypes.pzNoF  = zSixSpaces;
+    argTypes.pzSpc  = zThreeSpaces;
+
+    switch (pOpts->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:    argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case OPTPROC_LONGOPT:  argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case 0:                argTypes.pzOptFmt = zGnuOptFmt + 2; break;
+    case OPTPROC_SHORTOPT:
+        argTypes.pzOptFmt = zShrtGnuOptFmt;
+        zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
+        argTypes.pzOpt = " [arg]";
+        flen = 8;
+        break;
+    }
+
+    sprintf( zOptFmtLine, zFmtFmt, flen );
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   Figure out where all the initialization files might live.
+ *   This requires translating some environment variables and
+ *   testing to see if a name is a directory or a file.  It's
+ *   squishy, but important to tell users how to find these files.
+ */
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN )
+{
+    char zPath[ MAXPATHLEN+1 ];
+
+    if (papz == NULL)
+        return;
+
+    fputs( zPresetIntro, option_usage_fp );
+    *pInitIntro = AG_FALSE;
+
+    for (;;) {
+        const char* pzPath = *(papz++);
+
+        if (pzPath == NULL)
+            break;
+
+        if (optionMakePath( zPath, sizeof( zPath ), pzPath, pzPN ))
+            pzPath = zPath;
+
+        /*
+         *  Print the name of the "homerc" file.  If the "rcfile" name is
+         *  not empty, we may or may not print that, too...
+         */
+        fprintf( option_usage_fp, zPathFmt, pzPath );
+        if (*pzRc != NUL) {
+            struct stat sb;
+
+            /*
+             *  IF the "homerc" file is a directory,
+             *  then append the "rcfile" name.
+             */
+            if (  (stat( pzPath, &sb ) == 0)
+              &&  S_ISDIR( sb.st_mode ) ) {
+                fputc( '/', option_usage_fp );
+                fputs( pzRc, option_usage_fp );
+            }
+        }
+
+        fputc( '\n', option_usage_fp );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/usage.c */
diff --git a/sntp/libopts/version.c b/sntp/libopts/version.c
new file mode 100644 (file)
index 0000000..5817abc
--- /dev/null
@@ -0,0 +1,177 @@
+
+/*  $Id: version.c,v 4.5 2005/06/07 22:26:44 bkorb Exp $
+ * Time-stamp:      "2005-02-14 08:19:54 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ */
+
+static const char zAOV[] =
+    "Automated Options version %s, copyright (c) 1999-2005 Bruce Korb\n";
+
+/*  Automated Options is free software.
+ *  You may 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, or (at your option) any later version.
+ *
+ *  Automated Options 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 Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionVersion
+ *
+ * what:     return the compiled AutoOpts version number
+ * ret_type: const char*
+ * ret_desc: the version string in constant memory
+ * doc:
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+=*/
+const char*
+optionVersion( void )
+{
+    static const char zVersion[] =
+        STR( AO_CURRENT.AO_REVISION );
+
+    return zVersion;
+}
+
+
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp )
+{
+    char swCh;
+
+    if (pOD->pzLastArg == NULL)
+         swCh = 'v';
+    else swCh = pOD->pzLastArg[0];
+
+    if (pOpts->pzFullVersion != NULL)
+         fputs( pOpts->pzFullVersion, fp );
+    else fputs( pOpts->pzProgName,    fp );
+    fputc( '\n', fp );
+
+    switch (swCh) {
+    case NUL:
+    case 'v':
+    case 'V':
+        break;
+
+    case 'c':
+    case 'C':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+        }
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    case 'n':
+    case 'N':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+            fputc( '\n', fp );
+        }
+
+        if (pOpts->pzCopyNotice != NULL) {
+            fputs( pOpts->pzCopyNotice, fp );
+            fputc( '\n', fp );
+        }
+
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    default:
+        fprintf( stderr, zBadVerArg, swCh );
+        exit( EXIT_FAILURE );
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*=export_func  optionPrintVersion
+ * private:
+ *
+ * what:  Print the program version
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stdout.
+=*/
+void
+optionPrintVersion( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stdout );
+}
+
+/*=export_func  optionVersionStderr
+ * private:
+ *
+ * what:  Print the program version to stderr
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stderr.
+=*/
+void
+optionVersionStderr( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stderr );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/version.c */