This commit is contained in:
Graeme Walker 2001-09-08 12:00:00 +00:00
commit ead43a7739
182 changed files with 27444 additions and 0 deletions

4
AUTHORS Normal file
View File

@ -0,0 +1,4 @@
AUTHORS
=======
Graeme Walker <graeme_walker@users.sourceforge.net>

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

9
ChangeLog Normal file
View File

@ -0,0 +1,9 @@
Change Log
==========
0.9 -> 0.9.1
------------
Improved documentation from doxygen.
More complete use of namespaces.
Experimental compile-time support for IPv6.

189
INSTALL Normal file
View File

@ -0,0 +1,189 @@
Introduction
============
What follows are generic installation instructions for doing a
standard GNU "./configure; make; make install" installation from source.
The E-MailRelay userguide describes what you have to do after the "make
install" (under GNU/Linux) in order to get the emailrelay daemon to start
up at boot-time and automatically forward e-mail to your ISP.
Basic Installation
==================
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

2
Makefile.am Normal file
View File

@ -0,0 +1,2 @@
EXTRA_DIST =
SUBDIRS = src bin lib doc

352
Makefile.in Normal file
View File

@ -0,0 +1,352 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
EXTRA_DIST =
SUBDIRS = src bin lib doc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \
Makefile.am Makefile.in NEWS aclocal.m4 config.h.in configure \
configure.in install-sh missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
config.h: stamp-h
@if test ! -f $@; then \
rm -f stamp-h; \
$(MAKE) stamp-h; \
else :; fi
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=config.h \
$(SHELL) ./config.status
@echo timestamp > stamp-h 2> /dev/null
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
@if test ! -f $@; then \
rm -f $(srcdir)/stamp-h.in; \
$(MAKE) $(srcdir)/stamp-h.in; \
else :; fi
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f config.h
maintainer-clean-hdr:
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
all-recursive-am: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile config.h
all-redirect: all-recursive-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
install-data-recursive uninstall-data-recursive install-exec-recursive \
uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
all-recursive check-recursive installcheck-recursive info-recursive \
dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

10
NEWS Normal file
View File

@ -0,0 +1,10 @@
To do
=====
from 0.9.1
----------
Better use of autoconf
Port to BSD & solaris
test IPv6

67
README Normal file
View File

@ -0,0 +1,67 @@
E-MailRelay
===========
Abstract
--------
E-MailRelay is a simple store-and-forward SMTP MTA, designed for standalone
machines with an intermittent (dial-up) connection to the wider Internet.
In most situations the only configuration required is to specify the mail
gateway address on the command line.
C++ source code is available for Linux and Windows. Distribution is under
the GNU General Public License.
Quick start
-----------
The "emailrelay" program can be run as an SMTP server daemon using the
command "emailrelay --as-server", and stored mail can be forwarded by
running the command "emailrelay --as-client <isp-mail-server>:smtp".
The "--as-server" command is typically run automatically at boot time,
using the boot scripts under "/etc/init.d" or "/sbin/init.d", while the
"--as-client" command is normally put into pppd's "ip-up" script ("/etc/ppp/ip-up")
in place of "sendmail -q".
The program requires a writeable spool directory to store e-mail messages.
The directory defaults to "/usr/local/var/spool/emailrelay", but it
can be changed by using the "--spool-dir" switch.
By default the server will try to listen on TCP port 25. If another SMTP
server is running then it will fail to start up, with a "cannot bind" error
message. The port number can be changed by using the "--port" switch.
To test the program out without a full installation:
(1) run the server as "emailrelay --no-daemon --no-syslog --log --spool-dir ${HOME} --port 10001 &"
(2) reconfigure your e-mail client to use port 10001 rather than 25 ("smtp")
(3) send some test messages to addressees on the Internet
(4) connect to the Internet
(5) forward the stored messages using "emailrelay --spool-dir ${HOME} --as-client <your-isp-smtp-host>:smtp"
(6) clean up with "killall emailrelay ; rm ${HOME}/emailrelay.*"
Documentation
-------------
The following documentation is provided:
* README -- this document
* COPYING -- the GNU General Public License
* INSTALL -- build & install instructions (based on generic GNU text)
* doc/userguide.txt -- user guide
* doc/reference.txt -- reference document
* doc/developer.txt -- developer guide
And for completeness the following stub documents are also included:
* NEWS
* AUTHORS
* ChangeLog
Configurations
--------------
The code was developed on SuSE Linux 7.1 using:
* linux 2.2.18,
* gcc 2.95.2,
* glibc 2.2.7 (libc.so.6),
* gnu make 3.79.1,
* autoconf 2.13
and ported to Windows 98 using
* MSVC 6.0

127
aclocal.m4 vendored Normal file
View File

@ -0,0 +1,127 @@
dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])

10
bin/Makefile.am Normal file
View File

@ -0,0 +1,10 @@
noinst_SCRIPTS = emailrelay-filter.sh emailrelay-test.sh
libexec_SCRIPTS = emailrelay.sh
pkgdata_DATA = emailrelay-notify.sh emailrelay-deliver.sh
EXTRA_DIST = txt2html.sh $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA)
CLEANFILES = $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA)
TESTS = emailrelay-test.sh
SUFFIXES = .sh_ .sh
.sh_.sh:
cp $(srcdir)/../bin/$*.sh_ $*.sh
chmod ugo+x $*.sh

252
bin/Makefile.in Normal file
View File

@ -0,0 +1,252 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
noinst_SCRIPTS = emailrelay-filter.sh emailrelay-test.sh
libexec_SCRIPTS = emailrelay.sh
pkgdata_DATA = emailrelay-notify.sh emailrelay-deliver.sh
EXTRA_DIST = txt2html.sh $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA)
CLEANFILES = $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA)
TESTS = emailrelay-test.sh
SUFFIXES = .sh_ .sh
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
SCRIPTS = $(libexec_SCRIPTS) $(noinst_SCRIPTS)
DATA = $(pkgdata_DATA)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
.SUFFIXES: .sh .sh_
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps bin/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
install-libexecSCRIPTS: $(libexec_SCRIPTS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(libexecdir)
@list='$(libexec_SCRIPTS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`"; \
$(INSTALL_SCRIPT) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
else if test -f $(srcdir)/$$p; then \
echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`"; \
$(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
else :; fi; fi; \
done
uninstall-libexecSCRIPTS:
@$(NORMAL_UNINSTALL)
list='$(libexec_SCRIPTS)'; for p in $$list; do \
rm -f $(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
done
install-pkgdataDATA: $(pkgdata_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
@list='$(pkgdata_DATA)'; for p in $$list; do \
if test -f $(srcdir)/$$p; then \
echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgdatadir)/$$p"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgdatadir)/$$p; \
else if test -f $$p; then \
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p"; \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
fi; fi; \
done
uninstall-pkgdataDATA:
@$(NORMAL_UNINSTALL)
list='$(pkgdata_DATA)'; for p in $$list; do \
rm -f $(DESTDIR)$(pkgdatadir)/$$p; \
done
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = bin
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
check-TESTS: $(TESTS)
@failed=0; all=0; \
srcdir=$(srcdir); export srcdir; \
for tst in $(TESTS); do \
if test -f $$tst; then dir=.; \
else dir="$(srcdir)"; fi; \
if $(TESTS_ENVIRONMENT) $$dir/$$tst; then \
all=`expr $$all + 1`; \
echo "PASS: $$tst"; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
failed=`expr $$failed + 1`; \
echo "FAIL: $$tst"; \
fi; \
done; \
if test "$$failed" -eq 0; then \
banner="All $$all tests passed"; \
else \
banner="$$failed of $$all tests failed"; \
fi; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"; \
test "$$failed" -eq 0
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am: install-libexecSCRIPTS
install-exec: install-exec-am
install-data-am: install-pkgdataDATA
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-libexecSCRIPTS uninstall-pkgdataDATA
uninstall: uninstall-am
all-am: Makefile $(SCRIPTS) $(DATA)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libexecdir) $(DESTDIR)$(pkgdatadir)
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: uninstall-libexecSCRIPTS install-libexecSCRIPTS \
uninstall-pkgdataDATA install-pkgdataDATA tags distdir check-TESTS \
info-am info dvi-am dvi check check-am installcheck-am installcheck \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
.sh_.sh:
cp $(srcdir)/../bin/$*.sh_ $*.sh
chmod ugo+x $*.sh
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

74
bin/emailrelay-deliver.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# emailrelay-deliver.sh
#
# An example script which looks for local mail in the MailRelay
# spool directory, and delivers it using 'procmail'.
#
store="/var/spool/mailrelay"
postmaster="root"
# parse the command line
#
if test $# -ge 1
then
store="${1}"
fi
# check the spool directory is valid
#
if test \! -d "${store}"
then
echo `basename $0`: invalid spool directory >&2
exit 1
fi
# for each e-mail to a local recipient...
#
for file in ${store}/mail-relay.*.envelope.local ""
do
if test -f "${file}"
then
content="`echo ${file} | sed 's/envelope/content/'`"
deliver_to="`fgrep X-MailRelay-LocalTo ${file} | sed 's/X-MailRelay-LocalTo: //' | tr -d '\015' | sed \"s/postmaster/${postmaster}/g\"`"
if test "${deliver_to}" = ""
then
deliver_to="${postmaster}"
fi
# deliver using procmail
#
if test -f "${content}"
then
echo `basename $0`: delivering `basename ${content}` to ${deliver_to}
procmail -d ${deliver_to} < ${content}
rc=$?
if test "${rc}" -eq 0
then
echo '' # rm -f "${file}" 2>/dev/null
fi
fi
fi
done

194
bin/emailrelay-filter.sh Executable file
View File

@ -0,0 +1,194 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# A doxygen filter.
#
awk="gawk"
# PreFilter()
# Removes banner comments (including legalese) from the top of the file.
#
PreFilter()
{
${awk} ' BEGIN {
in_start = 1
}
{
if( in_start && !match( $0 , "^//" ) )
in_start = 0
if( !in_start )
print
} '
}
# SourceFilter()
# Adds doxygen annotation for implementation class comments.
#
SourceFilter()
{
${awk} ' BEGIN { in_class_comment = 0 }
{
start = match( $0 , "// Class:" ) == 1
end = match( $0 , "class" ) == 1
if( !in_class_comment && start )
{
in_class_comment = 1
print "/**"
}
else if( !in_class_comment )
{
print
}
else if( end )
{
in_class_comment = 0
print " */"
print
}
else
{
sub( "^// Description: " , "" )
sub( "^// See also: " , "\\see " )
sub( "^//" , "" )
printf( " * %s\n" , $0 )
}
}
'
}
# HeaderFilter()
# Adds doxygen annotation to header-file comments.
#
HeaderFilter()
{
${awk} ' BEGIN {
was_comment_line = 0
was_code_line = 0
re_namespace = "^[[:space:]]*namespace"
re_comment = "^[[:space:]]*//"
re_code = "^[[:space:]]*///"
}
{
is_namespace_line = match($0,re_namespace)
is_comment_line = match($0,re_comment)
re_comment_length = RLENGTH
is_code_line = match($0,re_code)
re_code_length = RLENGTH
if( is_namespace_line )
{
printf( "/*! \\namespace %s */\n" , $2 )
}
if( is_code_line )
{
sub( "///" , "//" )
}
if( is_comment_line )
{
indent = substr( $0 , 1 , re_comment_length-2 )
sub( "Class: " , "\\class " )
sub( "Typedef: .*" , "" )
sub( "Description: " , "" )
sub( "See also: " , "\\see " )
if( was_comment_line )
sub( re_comment , indent " " )
else if( length(indent) )
sub( re_comment , indent "/**<" )
else
sub( re_comment , indent "/** " )
}
if( is_code_line && !was_code_line )
{
print indent "\\code"
}
if( was_code_line && !is_code_line )
{
print indent "\\endcode"
}
if( was_comment_line && !is_comment_line )
{
print indent "*/"
}
print
was_comment_line = is_comment_line
was_code_line = is_code_line
} '
}
# PostFilter()
# Deals with nested-class descriptions with a format like "class Foo // comment".
#
PostFilter()
{
${awk} '
{
if( match( $0 , "^[[:space:]]*class[[:space:]][^/]*//" ) ||
match( $0 , "^[[:space:]]*struct[[:space:]][^/]*//" ) )
{
class = substr( $0 , 1 , RLENGTH-2 )
description = substr( $0 , RLENGTH+1 )
printf( " /** %s */\n" , description )
printf( "%s\n" , class )
}
else
{
print
}
} '
}
BasicFilter()
{
cat
echo '/* \\file */'
}
name="`basename \"${1}\"`"
type="`echo \"${name}\" | ${awk} -F . '{print $NF}'`"
classes="`fgrep '// Class:' \"${1}\" | wc -l`"
if test "${name}" = "gdef.h" -o "${name}" = "gnet.h"
then
cat "${1}" | BasicFilter
elif test "${type}" = "cpp" -a "${classes}" -eq 0
then
cat "${1}" | BasicFilter
elif test "${type}" = "cpp" -a "${classes}" -gt 0
then
cat "${1}" | SourceFilter
else
cat "${1}" | PreFilter | HeaderFilter | PostFilter
fi

94
bin/emailrelay-notify.sh Executable file
View File

@ -0,0 +1,94 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# emailrelay-notify.sh
#
# An example script which looks for failed mail in the MailRelay spool
# directory, and sends failure notification messages using 'procmail'.
#
tmp="/tmp/`basename $0`.$$.tmp"
trap "rm -f ${tmp} 2>/dev/null ; exit 0" 0 1 2 3 13 15
# parse the command line
#
store="/var/spool/mailrelay"
if test $# -ge 1
then
store="${1}"
fi
# check the spool directory
#
if test \! -d "${store}"
then
echo `basename $0`: invalid spool directory >&2
exit 1
fi
# for each failed e-mail...
#
for file in ${store}/mail-relay.*.envelope.bad ""
do
if test -f "${file}"
then
content="`echo ${file} | sed 's/envelope/content/' | sed 's/.bad//'`"
reason="`fgrep MailRelay-Reason ${file} | sed 's/X-[^ ]*Reason: //' | tr -d '\015'`"
from="`fgrep MailRelay-From ${file} | sed 's/X-MailRelay-From: //' | tr -d '\015'`"
deliver_to="${from}"
if test "${deliver_to}" = ""
then
deliver_to="postmaster"
fi
# create a notification message header
#
echo "To: ${deliver_to}" > ${tmp}
echo "From: postmaster" >> ${tmp}
echo "Subject: Your e-mail could not be delivered" >> ${tmp}
echo " " >> ${tmp}
# add the message content
#
if test "${reason}" != ""
then
echo "Reason: ${reason}" >> ${tmp}
fi
if test -f "${content}"
then
egrep -i '^To:|^Subject:' ${content} >> ${tmp}
echo " " >> ${tmp}
echo "The original mail is saved as \"${content}\"." >> ${tmp}
echo "You should make a copy of this file if necessary and then delete it." >> ${tmp}
fi
# deliver the notification using procmail
#
echo `basename $0`: delivering `basename ${content}` to ${deliver_to}
procmail -d ${deliver_to} < ${tmp}
rc=$?
if test "${rc}" -eq 0
then
rm -f "${file}" 2>/dev/null
fi
fi
done

148
bin/emailrelay-test.sh Executable file
View File

@ -0,0 +1,148 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# emailrelay-test.sh
#
# Test the E-MailRelay system.
#
# Creates three temporary spool directories under /tmp and runs
# three emailrelay servers to bucket-brigade a test message from one to
# the next. The test succeeds if the message gets into the third
# spool directory.
#
# If this test takes more than a second or two then it has failed.
#
exe="../src/main/emailrelay"
poke="../src/main/emailrelay-poke"
pp="1001" # port-prefix
base_dir="/tmp/`basename $0`.$$.tmp"
exit_code="1"
Cleanup()
{
kill `cat ${base_dir}/pid-* 2>/dev/null` 2>/dev/null
if test -d ${base_dir}
then
grep "." ${base_dir}/log-? > /tmp/`basename $0`.out 2>/dev/null
fi
rm -rf ${base_dir} 2>/dev/null
}
Trap()
{
Cleanup
exit ${exit_code}
}
RunServer()
{
port_="${1}"
spool_="${2}"
log_="${3}"
pidfile_="${4}"
extra_="${5}"
mkdir -p ${base_dir}/${spool_}
${exe} --log --no-syslog --port ${port_} --spool-dir ${base_dir}/${spool_} \
--pid-file ${base_dir}/${pidfile_} ${extra_} 2> ${base_dir}/${log_}
}
RunClient()
{
to_="${1}"
spool_="${2}"
log_="${3}"
pidfile_="${4}"
${exe} --forward --no-daemon --dont-serve --log --no-syslog \
--pid-file ${base_dir}/${pidfile_} \
--forward-to ${to_} --spool-dir ${base_dir}/${spool_} 2> ${base_dir}/${log_}
}
RunPoke()
{
port_="${1}"
log_="${2}"
${poke} ${port_} > ${base_dir}/${log_}
}
Content()
{
echo "To: recipient-1@localhost, recipient-2@localhost"
echo "Subject: test message 1"
echo "From: sender"
echo " "
echo "Content"
}
Envelope()
{
echo "X-MailRelay-Format: #2821.2"
echo "X-MailRelay-Content: 8bit"
echo "X-MailRelay-From: sender"
echo "X-MailRelay-ToCount: 2"
echo "X-MailRelay-To-Remote: recipient-1@localhost"
echo "X-MailRelay-To-Remote: recipient-2@localhost"
echo "X-MailRelay-End: 1"
}
CrLf()
{
sed 's/$/£/' | tr '£' '\r'
}
CheckResults()
{
if test -f ${base_dir}/store-3/*.envelope -a -f ${base_dir}/store-3/*.content
then
exit_code="0"
echo `basename $0`: succeeded
else
echo `basename $0`: failed: see /tmp/`basename $0`.out >&2
fi
}
StartTimer()
{
( sleep 5 ; Cleanup ) &
}
CreateMessages()
{
mkdir -p ${base_dir}/store-1
Content | CrLf > ${base_dir}/store-1/emailrelay.0.1.content
Envelope | CrLf > ${base_dir}/store-1/emailrelay.0.1.envelope
}
trap "Trap ; exit" 1 2 3 13 15
trap "Trap 0 ; exit" 0
StartTimer
RunServer ${pp}1 store-2 log-1 pid-1
RunServer ${pp}2 store-2 log-2 pid-2 "--admin ${pp}4 --forward-to localhost:${pp}3"
RunServer ${pp}3 store-3 log-3 pid-3
CreateMessages
RunClient localhost:${pp}1 store-1 log-c pid-4
RunPoke ${pp}4 log-p
CheckResults

71
bin/emailrelay.sh Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# emailrelay.sh
#
# A shell-script wrapper for E-MailRelay designed for
# use in the SysV-init system (/etc/init.d).
#
# usage: emailrelay.sh { start | stop }
#
# configuration
#
var_run="/var/run"
if test \! -d "${var_run}" ; then var_run="/tmp" ; fi
params=""
# initialisation
#
pid_file="${var_run}/emailrelay.pid"
# check the command line
#
usage="{ start | stop }"
if test $# -eq 0
then
echo usage: `basename $0` "${usage}" >&2
exit 2
fi
# process the command line
#
if test "${1}" = "start"
then
# "start"
#
rm -f "${pid_file}" 2>/dev/null
emailrelay --as-server --pid-file "${pid_file}" ${params} $@
elif test "${1}" = "stop"
then
# "stop"
#
if test -f "${pid_file}" && test "`cat ${pid_file}`" != ""
then
kill "`cat ${pid_file}`"
fi
else
echo usage: `basename $0` "${usage}" >&2
exit 2
fi

235
bin/txt2html.sh Executable file
View File

@ -0,0 +1,235 @@
#!/bin/sh
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
#
# txt2html.sh
#
awk="awk"
file="${1}"
if test "${file}" = ""
then
echo usage: `basename $0` '<txt-file>' >&2
exit 2
fi
if test \! -f "${file}"
then
echo `basename $0`: no such file: ${file} >&2
exit 1
fi
title="`basename ${file}`"
if test "${2}" != ""
then
title="${2}"
fi
# ===
Main()
{
${awk} -v title="${1}" '
BEGIN {
printf( "<html>\n" )
printf( "<head>\n" )
printf( "<title>%s</title>\n" , title )
printf( "</head>\n" )
printf( "<body>\n" )
}
function escape( line )
{
gsub( "&" , "\\&amp;" , line )
gsub( "<" , "\\&lt;" , line )
gsub( ">" , "\\&gt;" , line )
return line
}
function dequote( line )
{
quote = "\""
not_quote = "[^" quote "]"
gsub( quote not_quote "*" quote , "<b><em>&</em></b>" , line )
gsub( "<em>" quote , "<em>" , line )
gsub( quote "</em>" , "</em>" , line )
return line
}
function fn( line )
{
gsub( "[^[:space:]][^[:space:]]*\\(\\)" , "<i>&</i>" , line )
return line
}
function output( line )
{
printf( "%s\n" , fn(dequote(escape(line))) )
}
function tagOutput( line , tag )
{
printf( "<%s>%s</%s>\n" , tag , fn(dequote(escape(line))) , tag )
}
function process( line , next_ )
{
is_blank = match( line , "^[[:space:]]*$" )
is_sub_para = match( line , "^[[:space:]][[:space:]][^[:space:]]" )
is_code = match( line , "^[[:space:]]" ) && !is_sub_para
is_heading = match( next_ , "^==*[[:space:]]*$" )
is_sub_heading = match( next_ , "^--*[[:space:]]*$" )
is_list_item = match( line , "^\\* " )
is_numbered_item = match( line , "^\\([[:digit:]][[:digit:]]*\\)" )
is_heading_line = match( line , "^==*[[:space:]]*$" )
is_sub_heading_line = match( line , "^--*[[:space:]]*$" )
if( is_blank )
{
printf( "<p><br>\n" )
}
else if( is_code )
{
tagOutput( line , "pre" )
}
else if( is_sub_para )
{
tagOutput( line , "sub" )
}
else if( is_list_item )
{
gsub( "^\\* " , "" , line )
tagOutput( line , "li" )
}
else if( is_numbered_item )
{
gsub( "^\\([[:digit:]][[:digit:]]*\\) " , "" , line )
tagOutput( line , "LI" )
}
else if( is_heading )
{
printf( "<h1>%s</h1>\n" , line )
}
else if( is_sub_heading )
{
printf( "<h2>%s</h2>\n" , line )
}
else if( !is_heading_line && !is_sub_heading_line )
{
output( line )
}
}
{
if( NR != 1 )
process( previous , $0 )
previous = $0
}
END {
process( previous , "" )
printf( "</body>\n" )
printf( "</html>\n" )
} '
}
# ==
AugmentLists()
{
${awk} -v item_tag="${1}" -v list_tag="${2}" '
{
line = $0
is_list_item = match( line , "^<" item_tag ">.*</" item_tag ">$" )
if( is_list_item && !in_list )
printf( "<%s>\n" , list_tag )
else if( in_list && !is_list_item )
printf( "</%s>\n" , list_tag )
print
in_list = is_list_item
} '
}
# ==
Elide()
{
${awk} -v tag="${1}" '
{
line = $0
is_tag_line = match( line , "^<" tag ">.*</" tag ">$" )
core = substr( line , length(tag)+3 , length(line)-length(tag)-length(tag)-5 )
if( is_tag_line && !in_tag )
printf( "<%s>%s" , tag , core )
else if( is_tag_line && in_tag )
printf( "\n%s" , core )
else if( !is_tag_line && in_tag )
printf( "</%s>\n%s\n" , tag , line )
else
print line
in_tag = is_tag_line
} '
}
# ==
Compress()
{
${awk} '
function process( previous , line , next_ )
{
re_blank = "^<p><br>$"
re_heading = "^<[Hh][[:digit:]]>"
re_pre_start = "^<pre>"
re_pre_end = "</pre>$"
if( match(line,re_blank) && ( match(next_,re_heading) || match(previous,re_heading) ) )
{
}
else if( match(line,re_blank) && match(next_,re_pre_start) )
{
}
else
{
print line
}
}
{
if( NR >= 2 )
process( l2 , l1 , $0 )
l2 = l1
l1 = $0
}
END {
process( l2 , l1 , "" )
process( l1 , "" , "" )
}
'
}
# ==
cat "${file}" | Main "${title}" | Compress | AugmentLists li bl | AugmentLists LI ol | Elide "sub" | Elide "pre"

41
config.h.in Normal file
View File

@ -0,0 +1,41 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if you have the glob function. */
#undef HAVE_GLOB
/* Define if you have the socket function. */
#undef HAVE_SOCKET
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION

2222
configure vendored Executable file

File diff suppressed because it is too large Load Diff

46
configure.in Normal file
View File

@ -0,0 +1,46 @@
dnl
dnl Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
dnl
dnl This program is free software; you can redistribute it and/or
dnl modify it under the terms of the GNU General Public License
dnl as published by the Free Software Foundation; either
dnl version 2 of the License, or (at your option) any later
dnl version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dnl
dnl ===
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/main/gsmtp.h)
AM_INIT_AUTOMAKE(emailrelay,0.9.1)
AM_CONFIG_HEADER(config.h)
AC_LANG_CPLUSPLUS
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_CHECK_PROG(HAVE_DOXYGEN,doxygen,yes)
AC_CHECK_PROG(HAVE_MAN2HTML,man2html,yes)
dnl Checks for libraries.
dnl Checks for header files, functions and typedefs
AC_HEADER_STDC
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(sys/time.h)
AC_TYPE_SIZE_T
AC_CHECK_FUNCS(glob)
AC_CHECK_FUNCS(socket)
AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile bin/Makefile doc/Makefile)

39
doc/Makefile.am Normal file
View File

@ -0,0 +1,39 @@
EXTRA_DIST = developer.txt reference.txt userguide.txt index.html emailrelay.1 emailrelay-poke.1 index.html
noinst_SCRIPTS = .dox
pkgdata_DATA = readme.html developer.html reference.html userguide.html man.html index.html
CLEANFILES = $(pkgdata_DATA) $(noinst_SCRIPTS) html
SUFFIXES = .txt .html
filter=$(srcdir)/../bin/emailrelay-filter.sh
converter=$(srcdir)/../bin/txt2html.sh
.txt.html:
$(converter) $< > $*.html
.dox: $(filter)
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP__:$(top_srcdir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
man.html: emailrelay.1
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html emailrelay.1 > man.html ; else echo no man2html ; fi
$(filter): $(filter)_
@cp $(filter)_ $(filter)
@chmod ugo+x $(filter)
$(converter): $(converter)_
@cp $(converter)_ $(converter)
@chmod ugo+x $(converter)
developer.html reference.html userguide.html: $(converter)
readme.html: $(top_srcdir)/README $(converter)
$(converter) $(top_srcdir)/README > readme.html
install-data-local:
$(mkinstalldirs) $(destdir)$(mandir)/man1
$(INSTALL) $(top_srcdir)/doc/emailrelay.1 $(destdir)$(mandir)/man1/emailrelay.1
$(INSTALL) $(top_srcdir)/doc/emailrelay-poke.1 $(destdir)$(mandir)/man1/emailrelay-poke.1
$(mkinstalldirs) $(destdir)$(pkgdatadir)/html
if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in html/* ; do $(INSTALL) $$file $(destdir)$(pkgdatadir)/$$file ; done ; fi

239
doc/Makefile.in Normal file
View File

@ -0,0 +1,239 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
EXTRA_DIST = developer.txt reference.txt userguide.txt index.html emailrelay.1 emailrelay-poke.1 index.html
noinst_SCRIPTS = .dox
pkgdata_DATA = readme.html developer.html reference.html userguide.html man.html index.html
CLEANFILES = $(pkgdata_DATA) $(noinst_SCRIPTS) html
SUFFIXES = .txt .html
filter = $(srcdir)/../bin/emailrelay-filter.sh
converter = $(srcdir)/../bin/txt2html.sh
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
SCRIPTS = $(noinst_SCRIPTS)
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DATA = $(pkgdata_DATA)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
.SUFFIXES: .html .txt
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps doc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
install-pkgdataDATA: $(pkgdata_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
@list='$(pkgdata_DATA)'; for p in $$list; do \
if test -f $(srcdir)/$$p; then \
echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgdatadir)/$$p"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgdatadir)/$$p; \
else if test -f $$p; then \
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p"; \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
fi; fi; \
done
uninstall-pkgdataDATA:
@$(NORMAL_UNINSTALL)
list='$(pkgdata_DATA)'; for p in $$list; do \
rm -f $(DESTDIR)$(pkgdatadir)/$$p; \
done
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = doc
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am: install-pkgdataDATA install-data-local
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-pkgdataDATA
uninstall: uninstall-am
all-am: Makefile $(SCRIPTS) $(DATA)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: uninstall-pkgdataDATA install-pkgdataDATA tags distdir info-am \
info dvi-am dvi check check-am installcheck-am installcheck \
install-exec-am install-exec install-data-local install-data-am \
install-data install-am install uninstall-am uninstall all-redirect \
all-am all installdirs mostlyclean-generic distclean-generic \
clean-generic maintainer-clean-generic clean mostlyclean distclean \
maintainer-clean
.txt.html:
$(converter) $< > $*.html
.dox: $(filter)
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP__:$(top_srcdir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
man.html: emailrelay.1
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html emailrelay.1 > man.html ; else echo no man2html ; fi
$(filter): $(filter)_
@cp $(filter)_ $(filter)
@chmod ugo+x $(filter)
$(converter): $(converter)_
@cp $(converter)_ $(converter)
@chmod ugo+x $(converter)
developer.html reference.html userguide.html: $(converter)
readme.html: $(top_srcdir)/README $(converter)
$(converter) $(top_srcdir)/README > readme.html
install-data-local:
$(mkinstalldirs) $(destdir)$(mandir)/man1
$(INSTALL) $(top_srcdir)/doc/emailrelay.1 $(destdir)$(mandir)/man1/emailrelay.1
$(INSTALL) $(top_srcdir)/doc/emailrelay-poke.1 $(destdir)$(mandir)/man1/emailrelay-poke.1
$(mkinstalldirs) $(destdir)$(pkgdatadir)/html
if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in html/* ; do $(INSTALL) $$file $(destdir)$(pkgdatadir)/$$file ; done ; fi
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

161
doc/developer.txt Normal file
View File

@ -0,0 +1,161 @@
E-MailRelay Developer reference
===============================
Module structure
----------------
There are two C++ libraries in the E-MailRelay code: "glib" provides low-level
classes for file-system abstraction, date and time representation, string
utility functions, logging, command line parsing etc., and "gnet" provides
network classes using the Berkley socket and Winsock APIs. Both libraries
are portable between POSIX-like systems (eg. Linux) and Windows.
The application-level classes are implemented within the "GSmtp" namespace.
The key classes in this namespace are "ClientProtocol", "ServerProtocol" and
"MessageStore". The protocol and message-store functionality is brought
together by the high-level "GSmtp::Server" and "GSmtp::Client" classes.
Under Windows the "gnet" library needs to create hidden GUI windows in
order to receive network events. (Windows has historically built network
event processing on top of the GUI event system, rather then implementing
both GUI and network event handling on top of a generic event notification
system as POSIX systems do.) The Windows GUI and event classes are put into
a separate "src/win32" directory.
For a quick tour of the code look at the following headers:
* src/glib/gpath.h
* src/glib/gstr.h
* lib/gcc2.95/sstream
* src/gnet/gevent.h
* src/gnet/gaddress.h
* src/gnet/gsocket.h
* src/gnet/gserver.h
* src/main/gmessagestore.h
* src/main/gserverprotocol.h
* src/main/gsmtpserver.h
Directory structure
-------------------
* src
Parent directory for source code.
* src/glib
A low-level class library, including classes for file-system abstraction,
date and time, string utility functions, logging, command line parsing etc.
* src/gnet
A network library using Berkley sockets or Winsock.
* src/win32
Additional classes for windows event processing.
* src/main
Application-level classes for E-MailRelay.
* lib
Parent directory for ANSI C++ fixes
* lib/gcc2.95
Standard headers which are missing in gcc2.95
* lib/msvc6.0
Standard headers which are missing (or broken) in msvc6.0
Portability
-----------
The E-MailRelay code is written in ANSI C++, using the following
language/library features:
* templates
* exceptions
* namespaces
* "explicit"
* STL
* std::string & std::stringstream
* dynamic_cast<> & RTTI
* static_cast<> & const_cast<>
but not:
* defaulted template parameters
* templated member functions
* covariant return
* "mutable"
The header files "gdef.h" in "src/glib", and "gnet.h" in "src/gnet" are
intended to be used to fix up portability issues such as missing standard
types, non-standard system headers etc. Conditional compilation is not
used outside of these headers (with the odd exception).
Deficiencies in the ANSI C++ headers files provided by the compiler
are fixed up in the "lib" directory tree. For example, the msvc6.0
compiler sometimes does not put its names into the "std" namespace,
even though the std-namespace headers are used. This can be worked round
by additional "using" declarations in the "lib/msvc6.0" headers.
These work-rounds are kept out of the "src" tree because they are likely
to be fixed in later compiler releases. Standards-compliant compilers
should not need to include any headers from the "lib" directory tree.
Windows/unix portability is generally addressed by providing a common
class declaration with two implementations. Where necessary a pimple
pattern is used to hide the system-specific parts of the declaration.
A good example is the "GDirectory" class used for iterating through files
in a directory. The header file "src/glib/gdirectory.h" is common to both
systems, but two implementations are provided in "gdirectory_unix.cpp"
and "gdirectory_win32.cpp". The unix implementation uses opendir() and
glob(), while the windows implementation uses FindFirstFile().
Sometimes only parts of the implementation are system-specific. In these
cases there are three source files per header. For example, "gsocket.cpp",
"gsocket_win32.cpp" and "gsocket_unix.cpp" in the "src/gnet" directory.
Porting
-------
If trying a port using a good ANSI C++ compiler then start by removing
files from the "lib/gcc2.95" directory (or edit makefiles to remove the
include path), and then review the following header files: "src/glib/gdef.h",
"src/gnet/gnet.h", "src/glib/gmemory.h".
The unix (ie. POSIX-like) implementation of the directory iteration class
uses glob(). This functionality is only used by the message store code in
the "src/main" directory. If glob() presents a porting challenge then
the filename matching could be removed from the directory iterator and
moved into the message store class.
IPv6
----
IPv6 is supported at compile-time by selecting source files in the
"src/gnet" directory ending "_ipv6.cpp" rather than "_ipv4.cpp".
The code should be regarded as experimental.
Doxygen
-------
The commenting style used in header files is compatible with Doxygen
if passed through the simple awk-based preprocessor "emailrelay-filter.sh".
A "make" in the "doc" directory will run Doxygen if it is found on
your path.
Windows build
-------------
A simple project file "emailrelay.dsp" for msvc6.0 is provided in the
"src/main" directory.
Style
-----
Tabs are used for indenting, not multiple spaces, but only at the left
hand edge, and never within a line. This allows the reader to choose
how deep the indenting should be (appropriate to their window size) by
setting the editor's tabstop. Using spaces does not allow the reader this
freedom.
Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

35
doc/emailrelay-poke.1 Normal file
View File

@ -0,0 +1,35 @@
.\"
.\" Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
.\"
.\" This program is free software; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License
.\" as published by the Free Software Foundation; either
.\" version 2 of the License, or (at your option) any later
.\" version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
.\"
.TH EMAILRELAY 1 local
.SH NAME
emailrelay-poke \- e-mail transfer agent poke utility
.SH SYNOPSIS
.B emailrelay-poke
[ admin-port [ admin-command ] ]
.SH DESCRIPTION
.I emailrelay-poke
is a small utility which connects to the
.I emailrelay
administration interface and executes the
.B flush
command.
.SH SEE ALSO
.BR emailrelay (1)
.SH AUTHOR
Graeme Walker, mailto:graeme_walker@users.sourceforge.net

156
doc/emailrelay.1 Normal file
View File

@ -0,0 +1,156 @@
.\"
.\" Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
.\"
.\" This program is free software; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License
.\" as published by the Free Software Foundation; either
.\" version 2 of the License, or (at your option) any later
.\" version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
.\"
.TH EMAILRELAY 1 local
.SH NAME
emailrelay \- e-mail transfer agent
.SH SYNOPSIS
.B emailrelay
[OPTIONS]
.LP
.B emailrelay
--as-server
.LP
.B emailrelay
--as-client
.I server-address
.SH DESCRIPTION
.I emailrelay
is an simple e-mail message transfer agent. It is intended to be used
on stand-alone machines which have a dial-up connection to an ISP.
.LP
It runs in two modes: a storage deamon
.RI ( --as-server )
and a forwarding
agent
.RI ( --as-client ).
The storage daemon is an SMTP server which stores e-mail
messages in a local spool directory. The forwarding agent acts as an
SMTP client, which passes the spooled e-mail messages on to an ISP's SMTP
server.
.SH OPTIONS
.TP
.B \-a,--admin \fIadmin-port\fR
Enables the administration interface and specifies its listening port number.
.TP
.B \-d,--as-server
Equivalent to \fI--close-stderr\fR \fI--log\fR.
.TP
.B \-e,--close-stderr
Closes the standard error stream when daemonising.
.TP
.B \-f,--forward
Forwards stored mail on startup (requires \fI--forward-to\fR).
.TP
.B \-h,--help
Displays help text and exits.
.TP
.B \-i,--pid-file \fIpid-file\fR
Records the daemon process-id in the given file.
.TP
.B \-l,--log
Writes log information on standard error (if open) and syslog (if not disabled).
.TP
.B \-n,--no-syslog
Disables syslog output.
.TP
.B \-o,--forward-to \fIhost:port\fR
Specifies the remote smtp server (required by \fI--forward\fR and \fI--admin\fR).
.TP
.B \-p,--port \fIport\fR
Specifies the smtp listening port number.
.TP
.B \-q,--as-client \fIhost:port\fR
Equivalent to \fI--no-syslog\fR \fI--no-daemon\fR \fI--log\fR \fI--dont-serve\fR \fI--forward\fR \fI--forward-to\fR.
.TP
.B \-r,--remote-clients
Allows remote clients to connect.
.TP
.B \-s,--spool-dir \fIdir\fR
Specifies the spool directory (default is \fI/usr/local/var/spool/emailrelay\fR).
.TP
.B \-t,--no-daemon
Does not detach from the terminal.
.TP
.B \-v,--verbose
Generates more verbose logging (if compiled-in and logging enabled and stderr open).
.TP
.B \-x,--dont-serve
Stops the process acting as a server (usually used with \fI--forward\fR).
.TP
.B \-V,--version
Displays version information and exits.
.SH "DIAGNOSTICS"
If the
.IR --log ,
.I --as-client
or
.I --as-server
switches are in force then warning and error messages
are sent to
.I syslog
(using the
.BR LOG_MAIL
facility) and to
.IR stderr .
Output to
.I syslog
can be disabled with
.IR --no-syslog ,
and output to stderr can be disabled in daemon mode with
.IR --close-stderr .
.PP
Failed e-mail messages are kept in the spool directory and given
a
.I .bad
filename suffix. The failure reason is usually recorded within the
envelope file iteself.
.SH FILES
.IP \(bu 2
/usr/local/sbin/emailrelay
.IP \(bu 2
/usr/local/libexec/emailrelay-poke
.IP \(bu 2
/usr/local/libexec/emailrelay.sh
.IP \(bu 2
/usr/local/share/emailrelay/*.html
.IP \(bu 2
/usr/local/share/emailrelay/html/*.html
.IP \(bu 2
/usr/local/share/emailrelay/emailrelay-notify.sh
.IP \(bu 2
/usr/local/share/emailrelay/emailrelay-deliver.sh
.IP \(bu 2
/usr/local/man/man1/emailrelay.1
.IP \(bu 2
/usr/local/man/man1/emailrelay-poke.1
.IP \(bu 2
/usr/local/var/spool/emailrelay/emailrelay.*.envelope
.IP \(bu 2
/usr/local/var/spool/emailrelay/emailrelay.*.content
.SH SEE ALSO
E-MailRelay user guide
.br
E-MailRelay reference
.br
.BR syslog (3),
.BR pppd (8),
.BR init.d (7)
.BR emailrelay-poke (1),
.SH AUTHOR
Graeme Walker, mailto:graeme_walker@users.sourceforge.net

15
doc/index.html Normal file
View File

@ -0,0 +1,15 @@
<html>
<head>
</head>
<body>
<h1>E-MailRelay Documentation</h1>
<bl>
<li><a href=readme.html>Readme</a></li>
<li><a href=userguide.html>User guide</a></li>
<li><a href=reference.html>Reference manual</a></li>
<li><a href=developer.html>Notes for developers</a></li>
<li><a href=html/index.html>Source code documentation</a> (generated by <a href=http://www.doxygen.org>doxygen</a>)</li>
<li><a href=man.html>Man page</a> (generated by man2html)</li>
</bl>
</body>
</html>

190
doc/reference.txt Normal file
View File

@ -0,0 +1,190 @@
E-MailRelay Reference Manual
============================
Document
--------
This is the E-MailRelay reference guide. It contains material which is supplementary
to the user guide.
Usage
-----
The "emailrelay" program supports the following command-line usage:
emailrelay [<switch> [<switch> ...]]
where <switch> is:
* --version (-V)
Displays version information and exits.
* --admin (-a)
Enables the administration interface and specifies its listening port number.
* --as-server (-d)
Equivalent to "--close-stderr --log".
* --close-stderr (-e)
Closes the standard error stream when daemonising.
* --forward (-f)
Forwards stored mail on startup (requires --forward-to).
* --help (-h)
Displays help text and exits.
* --pid-file (-i)
Records the daemon process-id in the given file.
* --log (-l)
Writes log information on standard error (if open) and syslog (if not disabled).
* --no-syslog (-n)
Disables syslog output.
* --forward-to (-o)
Specifies the remote smtp server (required by --forward and --admin).
* --port (-p)
Specifies the smtp listening port number.
* --as-client (-q)
Equivalent to "--no-syslog --no-daemon --log --dont-serve --forward --forward-to".
* --remote-clients (-r)
Allows remote clients to connect.
* --spool-dir (-s)
Specifies the spool directory (default is "/usr/local/var/spool/emailrelay").
* --no-daemon (-t)
Does not detach from the terminal.
* --verbose (-v)
Generates more verbose logging (if compiled-in and logging enabled and stderr open).
* --dont-serve (-x)
Stops the process acting as a server (usually used with --forward).
If no command-line switches are supplied at all then the default
behaviour is:
* to run as a daemon, detached from the terminal
* listen on the standard SMTP port (25)
* store e-mail messages in "/usr/local/var/spool/emailrelay"
* reject connections from remote clients
* disable the administration interface
* generate no logging or diagnostic messages
To foward spooled messages to the ISP the command-line switch "--as-client"
is provided to run the program...
* in foreground, exiting when all spooled mail has been processed
* forwarding spooled mail from "/usr/local/var/spool/emailrelay"
* without listening on any port
* with error, warning and information messages sent to stderr
* without using syslog
The "--as-server" switch makes sure that logging is enabled and that
the standard error stream is closed.
Message store
-------------
Mail messages are stored as text files in the configured spool directory. Each
message is represented as an envelope file and a content file. The envelope
file contains parameters relevant to the SMTP dialogue, and the content file
contains the RFC822 headers and body text. Note that the content is largely
ignored by the SMTP protocol.
The filenames used in the message store have a prefix of "emailrelay", followed
by a process-id and sequence number, followed by "envelope" or "content". The
envelope files then have an additional suffix to implement a simple locking
scheme.
The envelope suffixes are:
* ".new" -- while the envelope is first being written
* <none> -- while the message is spooled
* ".busy" -- while the message is being forwarded
* ".bad" -- if the message cannot be forwarded
* ".local" -- for copies of the envelope file for delivery to local recipeints
Copies of the content file for delivery to local recipeints will also have
a "local" suffix.
If a message cannot be forwarded the envelope file is given a "bad" suffix,
and the failure reason is written into the file.
SMTP issues
-----------
Local delivery:
E-MailRelay will reject all local recipients, with the exception of "postmaster".
This is in line with its intended purpose as a simple mail relay, rather than
a fully-fledged routing MTA. Any addressee (except "postmaster") without an "at"
sign (@) will be rejected at the time the message is submitted by the e-mail
front-end.
Delivery of mail to a local "postmaster" is a feature of E-MailRelay which is
provided for completeness and for comformance to the SMTP specification. It is
only relevant if you are in the habit of sending mail to yourself as "postmaster";
mail to "postmaster" from an external source is not processed by E-MailRelay
and should be delivered normally.
Note that E-MailRelay daemon does not actually deliver mail to the postmaster
mailbox. All it does is create an envelope and content file in the spool directory
with a ".local" suffix. Some external system, such as a shell script run
from cron calling "procmail", should be used to process the ".local" files.
An example script is provided.
Timeouts:
Client-side timeouts are not implemented. If the ISP server is very slow then
in a typical setup the dial-up line will be dropped due to inactivity. This
will have the desired effect of aborting the message submission.
Message loops:
Message loops are not detected.
Eight bit messages:
The 8BITMIME SMTP extension is supported, however no attempt is made to
re-encode 8-bit messages into 7-bit messages if the downstream server
does not.
Administration interface
------------------------
If enabled, the server will provide a network interface for performing administration
tasks. This is a simple command-line interface which is compatible with telnet.
Currently the only supported command is "flush", which tries to forward spooled mail
to the configured dowstream SMTP server. The downstream server address must have been
defined on the "emailrelay" command line at start-up using the "--forward-to" switch;
it cannot be specified through the administration interface.
Security issues
---------------
E-MailRelay runs with a umask of 177. It does not call exec() or system(). It does not
change its effective userid. No configuration parameters can be changed through the
administrative interface. By default connections to the SMTP and administrative ports
will be rejected if they come from remote machines.
Files
-----
By default "make install" installs the following files:
* /usr/local/sbin/emailrelay
* /usr/local/libexec/emailrelay-poke
* /usr/local/libexec/emailrelay.sh
* /usr/local/var/spool/emailrelay/empty_file
* /usr/local/share/emailrelay/emailrelay-notify.sh
* /usr/local/share/emailrelay/emailrelay-deliver.sh
This directory structure is constrained by the autoconf and GNU standards. Preferred
locations would be something like this:
* /usr/sbin/emailrelay
* /opt/emailrelay/bin/emailrelay-poke
* /sbin/init.d/emailrelay.sh
* /var/spool/emailrelay/
* /opt/emailrelay/examples/emailrelay-notify.sh
* /opt/emailrelay/examples/emailrelay-deliver.sh
Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

188
doc/userguide.txt Normal file
View File

@ -0,0 +1,188 @@
E-MailRelay User Guide
======================
Document
--------
This document is the user guide for E-MailRelay V0.9.1.
What is it?
-----------
E-MailRelay is a simple e-mail store-and-forward transfer agent. It's a program
which runs in the background and accepts e-mail front-ends (KMail, Mutt, Netscape etc.),
stores the messages on the hard disk, and when next connected to the Internet forwards
them to a downstream SMTP server for onward delivery.
The E-MailRelay program ("emailrelay") can run in two modes: a storage daemon, or
a forwarding agent. As a storage daemon it waits for connections from your
e-mail front-end and stores the mail which it receives in a spool directory.
As a forwarding agent it pulls messages out of the spool directory and passes
them on to a remote server -- typically an ISP mail server.
E-MailRelay uses the Simple Message Transfer Protocol (SMTP). When running as a
storage daemon it acts as an SMTP server, and when running as a forwarding agent it
acts as an SMTP client.
E-MailRelay runs on GNU/Linux and Windows.
What it's not
-------------
E-MailRelay does not get involved in processing incoming e-mail messages; it only
operates on outgoing messages. Incoming e-mail messages will probably be retrieved
from your ISP by your e-mail front-end program, using the POP3 or IMAP protocols.
E-MailRelay is not a routing MTA. It is designed to be used in situations where all
outgoing e-mail message go out to the Internet, so it is not an appropriate choice
if you send e-mail to other people who use the same machine or to people who are
on the same local area network.
Why use it?
-----------
The motivation for developing E-MailRelay is that e-mail store-and-forward using
SMTP is conceptually a very simple thing, but most popular MTAs are complex.
E-MailRelay just stores messages and then forwards them on to your ISP, whereas a
fully-featured MTA does clever things with address re-writing, message routing,
local delivery, loop detection, fancy DNS lookups etc.
In particular the configuration of some popular MTAs is notoriously complex
and arcane, whereas the only thing the E-MailRelay system needs is the name of
your ISP's mail server.
With the move away from dial-up Internet connections a simple store-and-forward
MTA like E-MailRelay becomes more relevant to mobile computers and PDAs which
need to store mail while away from the network.
The source code for E-MailRelay is well-structured, portable ANSI C++, without any
thrid-party library dependencies. It could therefore be the basis for other SMTP
projects such as, for example, a protocol bridge between SMTP and proprietary mail
transfer protocols used in private e-mail networks.
Running E-MailRelay
-------------------
To run E-MailRelay as a storage daemon use the command:
emailrelay --as-server
To run E-MailRelay as a forwarding agent (once connected to the Internet), use a
command like this:
emailrelay --as-client mail.myisp.net:smtp
where "mail.myisp.net" is replaced with the name of your ISP's SMTP server.
(E-MailRelay can also combine the two roles of storage daemon and forwarding
client in one process. In this mode the storage service is always available,
but the forwarding activity has to be triggered via the "administration"
interface. The administration interface is a command-line network service
compatible with telnet. The interface must be enabled using the "--admin"
command line switch, specifying the listening port number.)
For more information on the command-line options refer to the reference guide
or run:
emailrelay --help
Starting the daemon at boot-time
--------------------------------
The standard installation of E-MailRelay (using "make install") puts most of the
files into the right places, but it does not set things up so that the daemon
starts at boot time, or that e-mail gets forwarded automatically when you
connect to the Internet. You have to do those bits yourself because of the
differences between the various GNU/Linux distributions.
Many systems, including the most popular GNU/Linux distributions, use the
System-V mechanism for starting daemons at boot time. The directory "/etc/init.d"
(or "/sbin/init.d") contains a start/stop script for each daemon process, and
then symbolic links in the "rc<N>.d" subdirectories control which scripts are
run when entering or leaving a particular run-level (<N>). The links point back
into the start/stop script in the parent directory, using a "S" prefix for the
starting link, and a "K" prefix for the stopping link. The numeric part of
the link name determines the order in which the links are called.
Before you start you will need to know where your "init.d" directory can be found
and what your default run level is:
$ ls -d /*/init.d
$ runlevel | awk '{print $2}'
Assuming these are "/etc/init.d" and "5" you should (as root) copy the E-MailRelay
start/stop script into "/etc/init.d":
$ cp /usr/local/libexec/emailrelay.sh /etc/init.d
Then determine an appropriate numeric value for the link names by looking at
the "sendmail" links:
$ cd /etc/init.d/rc5.d
$ ls *sendmail*
Assuming sendmail links are "S10sendmail" and "K10sendmail", create
the "emailrelay" links in the same format:
$ cd /etc/init.d/rc5.d
$ ln -s ../emailrelay.sh S10emailrelay
$ ln -s ../emailrelay.sh K10emailrelay
And finally remove sendmail from the run-level (otherwise both
daemons compete for the standard SMTP listening port):
$ cd /etc/init.d/rc5.d
$ rm *sendmail
(There are also KDE and GNOME GUIs which you can use to do the latter steps.)
Automatic triggering of onward delivery
---------------------------------------
This section assumes that you are using "pppd" to establish your dial-up Internet
connection. (Note that KDE's "kppp" and Red Hat's "rp3" are graphical front-ends
to the underlying "pppd" daemon.)
The ppp daemon calls the script "/etc/ppp/ip-up" when it has successfully established
a dial-up link to your ISP. This script will probably set up IP routes, update the
DNS configuration, initialise a firewall, run "fetchmail" and "sendmail", etc. It may
also call out to another script, "ip-up.local" which is available for you to put
stuff into without having to grub around inside "ip-up" itself.
The simplest approach for editing "ip-up" is to look for a "sendmail -q" line. If
you find "sendmail -q" then it should be sufficient to replace it with this:
emailrelay --as-client <myisp>:smtp
where you substitute your ISP's SMTP server address for <myisp>.
Or if your "ip-up" calls out to "ip-up.local" then create a two-line "ip-up.local"
script:
$ cd /etc/ppp
$ cat << EOF > ip-up.local
#!/bin/sh
exec /usr/local/sbin/emailrelay --as-client <myisp>:smtp
EOF
$ chmod +x ip-up.local
Glossary
--------
ISP = Internet Service Provider. The company your modem calls to connect to the Internet.
MTA = Message Transfer Agent. Something which accepts incoming e-mail messages and
passes them on either to a local user, or to another MTA. A sophisticated MTA program,
which is widely used on the Internet, is "sendmail".
SMTP = Simple Message Transfer Protocol. A set of rules which dictate how e-mail messages
are passed from one part of the e-mail system to the next. The protocol rules are set
out in the document called RFC2821.
POP3 = Post Office Protocol 3. A protocol for fetching incoming e-mail messages from your
ISP's mail server. Many e-mail front-ends (Mutt, KMail, Netscape, etc) will fetch messages
directly from your ISP using the POP protocol, or you may have a program like "fetchmail"
doing it on their behalf.
IMAP = Internet Message Access Protocol. A newer alternative to POP3.
PPP = Point to Point Protocol. A low-level protocol used in dial-up connections to an ISP.
Usually implemented by the "pppd" program on GNU/Linux.
Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

251
install-sh Executable file
View File

@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

1
lib/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = gcc2.95 msvc6.0

275
lib/Makefile.in Normal file
View File

@ -0,0 +1,275 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
SUBDIRS = gcc2.95 msvc6.0
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = lib
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-tags distclean-generic clean-am
distclean: distclean-recursive
maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
.PHONY: install-data-recursive uninstall-data-recursive \
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
uninstalldirs-recursive all-recursive check-recursive \
installcheck-recursive info-recursive dvi-recursive \
mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

22
lib/gcc2.95/Makefile.am Normal file
View File

@ -0,0 +1,22 @@
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
EXTRA_DIST = exception iostream limits sstream xlocale

191
lib/gcc2.95/Makefile.in Normal file
View File

@ -0,0 +1,191 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
EXTRA_DIST = exception iostream limits sstream xlocale
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/gcc2.95/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = lib/gcc2.95
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

37
lib/gcc2.95/exception Normal file
View File

@ -0,0 +1,37 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// exception
//
#ifndef G_STD_EXCEPTION
#define G_STD_EXCEPTION
namespace std
{
class exception
{
public:
virtual const char * what() const = 0 ;
} ;
} ;
#endif

36
lib/gcc2.95/iostream Normal file
View File

@ -0,0 +1,36 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// iostream
//
#ifndef G_STD_IOSTREAM
#define G_STD_IOSTREAM
// gnu's iostream does only this
#include <iostream.h>
namespace std
{
typedef ::ios ios_base ;
} ;
#endif

33
lib/gcc2.95/limits Normal file
View File

@ -0,0 +1,33 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// limits
//
#ifndef G_STD_LIMITS_H
#define G_STD_LIMITS_H
namespace std
{
#include <limits.h>
} ;
#endif

67
lib/gcc2.95/sstream Normal file
View File

@ -0,0 +1,67 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// sstream
//
// Forwards compatibility from ostrstream to std::stringstream.
//
#ifndef G_STD_SSTREAM_H
#define G_STD_SSTREAM_H
#include <strstream.h>
#include <string>
namespace std
{
class stringstream : public ostrstream
{
public:
stringstream() ;
stringstream( char * , size_t ) ;
std::string str() const ;
} ;
} ;
inline
std::stringstream::stringstream()
{
}
inline
std::stringstream::stringstream( char * , size_t )
{
}
inline
std::string std::stringstream::str() const
{
std::stringstream * This = const_cast<std::stringstream*>(this) ;
ostrstream * base = This ;
(*base) << '\0' ;
char * p = base->str() ;
std::string s( p ? p : "" ) ;
base->rdbuf()->freeze( 0 ) ;
return s ;
}
#endif

30
lib/gcc2.95/xlocale Normal file
View File

@ -0,0 +1,30 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// xlocale
//
#ifndef G_STD_XLOCALE
#define G_STD_XLOCALE
// empty
#endif

21
lib/msvc6.0/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
EXTRA_DIST = cstdio cstdlib cstring ctime

191
lib/msvc6.0/Makefile.in Normal file
View File

@ -0,0 +1,191 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
EXTRA_DIST = cstdio cstdlib cstring ctime
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/msvc6.0/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = lib/msvc6.0
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

35
lib/msvc6.0/cstdio Normal file
View File

@ -0,0 +1,35 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// cstdio
//
#ifndef G_PORT_CSTDIO_H
#define G_PORT_CSTDIO_H
#include <stdio.h>
namespace std
{
using ::remove ;
using ::rename ;
} ;
#endif

35
lib/msvc6.0/cstdlib Normal file
View File

@ -0,0 +1,35 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// cstdlib
//
#ifndef G_PORT_CSTDLIB_H
#define G_PORT_CSTDLIB_H
#include "stdlib.h"
namespace std
{
using ::rand ;
using ::srand ;
using ::getenv ;
} ;
#endif

43
lib/msvc6.0/cstring Normal file
View File

@ -0,0 +1,43 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// cstring
//
#ifndef G_PORT_CSTRING_H
#define G_PORT_CSTRING_H
#include "string.h"
namespace std
{
using ::strlen ;
using ::strcat ;
using ::strncat ;
using ::strchr ;
using ::strrchr ;
using ::strdup ;
using ::strcpy ;
using ::strstr ;
using ::strspn ;
using ::strcspn ;
} ;
#endif

40
lib/msvc6.0/ctime Normal file
View File

@ -0,0 +1,40 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// ctime
//
#ifndef G_PORT_CTIME_H
#define G_PORT_CTIME_H
#include <time.h>
namespace std
{
using ::time_t ;
using ::tm ;
using ::time ;
using ::localtime ;
using ::gmtime ;
using ::mktime ;
using ::_tzset ;
} ;
#endif

190
missing Executable file
View File

@ -0,0 +1,190 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

40
mkinstalldirs Executable file
View File

@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

1
src/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = glib gnet main win32

275
src/Makefile.in Normal file
View File

@ -0,0 +1,275 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
SUBDIRS = glib gnet main win32
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-tags distclean-generic clean-am
distclean: distclean-recursive
maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
.PHONY: install-data-recursive uninstall-data-recursive \
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
uninstalldirs-recursive all-recursive check-recursive \
installcheck-recursive info-recursive dvi-recursive \
mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

73
src/glib/Makefile.am Normal file
View File

@ -0,0 +1,73 @@
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
EXTRA_DIST=garg_win32.cpp \
gdaemon_win32.cpp \
gdatetime_win32.cpp \
gdirectory_win32.cpp \
gfs_win32.cpp \
glogoutput_win32.cpp \
gpid_win32.cpp \
gfile_win32.cpp \
gnumber.cpp
INCLUDES = -I$(top_srcdir)/lib/gcc2.95
noinst_LIBRARIES = libglib.a
libglib_a_SOURCES = garg.cpp \
garg_unix.cpp \
gdaemon_unix.cpp \
gdate.cpp \
gdatetime.cpp \
gdatetime_unix.cpp \
gdirectory.cpp \
gdirectory_unix.cpp \
gexception.cpp \
gfile.cpp \
gfile_unix.cpp \
gfs_unix.cpp \
ggetopt.cpp \
glog.cpp \
glogoutput.cpp \
glogoutput_unix.cpp \
gpath.cpp \
gpid_unix.cpp \
gstr.cpp \
gtime.cpp \
gdef.h \
garg.h \
gdaemon.h \
gdate.h \
gdatetime.h \
gdirectory.h \
gexception.h \
gfile.h \
gfs.h \
ggetopt.h \
glog.h \
glogoutput.h \
gnumber.h \
gpath.h \
gpid.h \
gstr.h \
gtime.h \
gstrings.h \
gdebug.h \
gassert.h \
gconvert.h \
gmemory.h

292
src/glib/Makefile.in Normal file
View File

@ -0,0 +1,292 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CXX = @CXX@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
EXTRA_DIST = garg_win32.cpp gdaemon_win32.cpp gdatetime_win32.cpp gdirectory_win32.cpp gfs_win32.cpp glogoutput_win32.cpp gpid_win32.cpp gfile_win32.cpp gnumber.cpp
INCLUDES = -I$(top_srcdir)/lib/gcc2.95
noinst_LIBRARIES = libglib.a
libglib_a_SOURCES = garg.cpp garg_unix.cpp gdaemon_unix.cpp gdate.cpp gdatetime.cpp gdatetime_unix.cpp gdirectory.cpp gdirectory_unix.cpp gexception.cpp gfile.cpp gfile_unix.cpp gfs_unix.cpp ggetopt.cpp glog.cpp glogoutput.cpp glogoutput_unix.cpp gpath.cpp gpid_unix.cpp gstr.cpp gtime.cpp gdef.h garg.h gdaemon.h gdate.h gdatetime.h gdirectory.h gexception.h gfile.h gfs.h ggetopt.h glog.h glogoutput.h gnumber.h gpath.h gpid.h gstr.h gtime.h gstrings.h gdebug.h gassert.h gconvert.h gmemory.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I../..
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libglib_a_LIBADD =
libglib_a_OBJECTS = garg.o garg_unix.o gdaemon_unix.o gdate.o \
gdatetime.o gdatetime_unix.o gdirectory.o gdirectory_unix.o \
gexception.o gfile.o gfile_unix.o gfs_unix.o ggetopt.o glog.o \
glogoutput.o glogoutput_unix.o gpath.o gpid_unix.o gstr.o gtime.o
AR = ar
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(libglib_a_SOURCES)
OBJECTS = $(libglib_a_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .cpp .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/glib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
libglib.a: $(libglib_a_OBJECTS) $(libglib_a_DEPENDENCIES)
-rm -f libglib.a
$(AR) cru libglib.a $(libglib_a_OBJECTS) $(libglib_a_LIBADD)
$(RANLIB) libglib.a
.cpp.o:
$(CXXCOMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src/glib
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-tags distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
check-am installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

140
src/glib/garg.cpp Normal file
View File

@ -0,0 +1,140 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// garg.cpp
//
#include "gdef.h"
#include "garg.h"
#include "gpath.h"
#include "gstr.h"
#include "gdebug.h"
#include "gassert.h"
G::Arg::Arg()
{
// now use parse()
}
G::Arg::Arg( const Arg & other ) :
m_array(other.m_array) ,
m_prefix(other.m_prefix)
{
}
G::Arg & G::Arg::operator=( const Arg & rhs )
{
if( this != &rhs )
{
m_array = rhs.m_array ;
m_prefix = rhs.m_prefix ;
}
return *this ;
}
G::Arg::~Arg()
{
}
G::Arg::Arg( int argc , char *argv[] )
{
for( int i = 0 ; i < argc ; i++ )
m_array.push_back( argv[i] ) ;
setPrefix() ;
}
void G::Arg::setPrefix()
{
G_ASSERT( m_array.size() > 0U ) ;
Path path( m_array[0U] ) ;
path.removeExtension() ;
m_prefix = path.basename() ;
}
void G::Arg::parse( HINSTANCE hinstance , const std::string & command_line )
{
m_array.push_back( moduleName(hinstance) ) ;
G::Str::splitIntoTokens( command_line , m_array , " \t" ) ;
setPrefix() ;
}
bool G::Arg::contains( const std::string & sw , size_t sw_args ) const
{
return find( sw , sw_args , NULL ) ;
}
bool G::Arg::find( const std::string & sw , size_t sw_args , size_t * index_p ) const
{
for( size_t i = 1 ; i < m_array.size() ; i++ ) // start from v[1]
{
if( sw == m_array[i] && (i+sw_args) < m_array.size() )
{
if( index_p != NULL )
*index_p = i ;
return true ;
}
}
return false ;
}
void G::Arg::remove( const std::string & sw , size_t sw_args )
{
size_t i = 0U ;
const bool found = find( sw , sw_args , &i ) ;
if( found )
removeAt( i , sw_args ) ;
}
void G::Arg::removeAt( size_t sw_index , size_t sw_args )
{
G_ASSERT( sw_index > 0U && sw_index < m_array.size() ) ;
if( sw_index > 0U && sw_index < m_array.size() )
{
Array::iterator p = m_array.begin() + sw_index ;
p = m_array.erase( p ) ;
for( size_t i = 0U ; i < sw_args && p != m_array.end() ; i++ )
p = m_array.erase( p ) ;
}
}
size_t G::Arg::index( const std::string & sw , size_t sw_args ) const
{
size_t i = 0U ;
const bool found = find( sw , sw_args , &i ) ;
return found ? i : 0U ;
}
size_t G::Arg::c() const
{
return m_array.size() ;
}
std::string G::Arg::v( size_t i ) const
{
G_ASSERT( i < m_array.size() ) ;
return m_array[i] ;
}
std::string G::Arg::prefix() const
{
return m_prefix ;
}

114
src/glib/garg.h Normal file
View File

@ -0,0 +1,114 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// garg.h
//
#ifndef G_ARG_H
#define G_ARG_H
#include "gdef.h"
#include <vector>
#include <string>
namespace G
{
class Arg ;
} ;
// Class: G::Arg
// Description: A command line parser class.
//
// Also does command line splitting for Windows:
// the single command line string is split into
// an argv[] array, including argv[0].
//
class G::Arg
{
public:
Arg( int argc , char *argv[] ) ;
// Constructor taking argc/argv.
Arg() ;
// Default constructor for Windows.
// Initialise (once) with parse().
void parse( HINSTANCE hinstance , const std::string & command_line ) ;
// Windows only.
//
// Parses the given command line, splitting
// it up into an array of tokens.
// The program name is automatically
// added as the first token (cf. argv[0]).
~Arg() ;
// Destructor.
unsigned int c() const ;
// Returns the number of tokens in the
// command line, including the program
// name.
std::string v( size_t i ) const ;
// Returns the i'th argument.
// Precondition: i < c()
std::string prefix() const ;
// Returns the basename of v(0) without
// any extension.
bool contains( const std::string & sw , size_t sw_args = 0U ) const ;
// Returns true if the command line
// contains the given switch with enough
// command line arguments left to satisfy
// the given number of switch arguments.
size_t index( const std::string & sw , size_t sw_args = 0U ) const ;
// Returns the index of the given switch.
// Returns zero if not present.
void remove( const std::string & sw , size_t sw_args = 0U ) ;
// Removes the given switch and its
// arguments.
//
// Precondition: contains()
void removeAt( size_t sw_index , size_t sw_args = 0U ) ;
// Removes the given argument and the
// following <sw_args> ones.
Arg & operator=( const Arg & ) ;
// Assignment operator.
Arg( const Arg & ) ;
// Copy constructor.
private:
static std::string moduleName( HINSTANCE h ) ;
bool find( const std::string & sw , size_t sw_args , size_t *index_p ) const ;
void setPrefix() ;
private:
typedef std::vector<std::string GAllocator(std::string) > Array ;
Array m_array ;
std::string m_prefix ;
} ;
#endif

32
src/glib/garg_unix.cpp Normal file
View File

@ -0,0 +1,32 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// garg_unix.cpp
//
#include "gdef.h"
#include "garg.h"
#include "gdebug.h"
std::string G::Arg::moduleName( HINSTANCE hinstance )
{
return std::string() ;
}

37
src/glib/garg_win32.cpp Normal file
View File

@ -0,0 +1,37 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// garg_win32.cpp
//
#include "gdef.h"
#include "garg.h"
#include "gdebug.h"
std::string G::Arg::moduleName( HINSTANCE hinstance )
{
char buffer[260] ;
size_t size = sizeof(buffer) ;
*buffer = '\0' ;
::GetModuleFileName( hinstance , buffer , size-1U ) ;
buffer[size-1U] = '\0' ;
return std::string(buffer) ;
}

37
src/glib/gassert.h Normal file
View File

@ -0,0 +1,37 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gassert.h
//
#ifndef G_ASSERT_H
#define G_ASSERT_H
#include "gdef.h"
#include "glogoutput.h"
#if defined(_DEBUG) && ! defined(G_NO_ASSERT)
#define G_ASSERT( test ) G::LogOutput::assertion( __FILE__ , __LINE__ , test , #test )
#else
#define G_ASSERT( test )
//#define G_ASSERT( test ) G::LogOutput::assertion( 0 , 0 , test , NULL )
#endif
#endif

48
src/glib/gconvert.h Normal file
View File

@ -0,0 +1,48 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gconvert.h
//
#ifndef G_CONVERT_H
#define G_CONVERT_H
#include "gdef.h"
#include "gexception.h"
G_EXCEPTION( GConvertOverflow , "arithmetic overflow" ) ;
// Template function: GConvert
// Description: Does arithmetic conversions with
// overflow checking.
//
template <class Tout, class Tin>
inline
Tout GConvert( const Tin & in )
{
Tout out = in ;
Tin copy = out ;
if( in != copy )
throw GConvertOverflow( std::stringstream() << in ) ;
return out ;
}
#endif

79
src/glib/gdaemon.h Normal file
View File

@ -0,0 +1,79 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdaemon.h
//
#ifndef G_DAEMON_H
#define G_DAEMON_H
#include "gdef.h"
#include "gexception.h"
#include "gpath.h"
#include <sys/types.h>
#include <string>
namespace G
{
class Daemon ;
} ;
// Class: G::Daemon
// Description: A class for deamonising the calling process.
// Deamonisation includes fork()ing, detaching from the
// controlling terminal, setting the process umask, etc.
// The windows implementation does nothing.
//
class G::Daemon
{
public:
G_EXCEPTION( CannotFork , "cannot fork" ) ;
G_EXCEPTION( BadPidFile , "invalid pid file" ) ;
enum Who { Parent , Child } ;
static void detach() ;
// Detaches from the parent environment.
// This typically involves fork()ing,
// _exit()ing the parent, and calling
// setsid() in the child.
static void detach( const Path & pid_file ) ;
// An overload which writes the new process-id
// to a file. The path must be absolute.
// Throws BadPidFile on error.
static void closeFiles( bool keep_stderr = false ) ;
// Closes all open file descriptors.
static void closeStderr() ;
// Closes stderr.
static void setUmask() ;
// Sets a tight umask.
private:
Daemon() ;
static Who fork() ;
static void setsid() ;
static void cd( const std::string & ) ;
} ;
#endif

107
src/glib/gdaemon_unix.cpp Normal file
View File

@ -0,0 +1,107 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdaemon_unix.cpp
//
#include "gdef.h"
#include "gdaemon.h"
#include "gpid.h"
//static
void G::Daemon::detach( const Path & pid_file )
{
if( !pid_file.isAbsolute() )
throw BadPidFile(std::string("must be an absolute path: ")+pid_file.str()) ;
if( !std::ofstream(pid_file.str().c_str()).good() )
throw BadPidFile(std::string("cannot create file: ")+pid_file.str()) ;
detach() ;
std::ofstream file( pid_file.str().c_str() ) ;
file << Pid() << std::endl ;
}
//static
void G::Daemon::detach()
{
// see Stevens, ISBN 0-201-563137-7, ch 13.
if( fork() == Parent )
::_exit( 0 ) ;
setsid() ;
cd( "/" ) ;
if( fork() == Parent )
::_exit( 0 ) ;
}
void G::Daemon::setsid()
{
pid_t session_id = ::setsid() ;
if( session_id == -1 )
; // no-op
}
void G::Daemon::cd( const std::string & dir )
{
if( 0 != ::chdir( dir.c_str() ) )
; // ignore it
}
void G::Daemon::setUmask()
{
// (note that ansi std::ofstream does not support file permissions,
// so rely on the umask to keep things secure)
mode_t new_mode = 0177 ; // create as -rw-------
mode_t old_mode = ::umask( new_mode ) ;
}
G::Daemon::Who G::Daemon::fork()
{
pid_t pid = ::fork() ;
if( pid < 0 )
{
throw CannotFork() ;
}
return pid == 0 ? Child : Parent ;
}
void G::Daemon::closeStderr()
{
::close( STDERR_FILENO ) ;
}
void G::Daemon::closeFiles( bool keep_stderr )
{
int n = 256U ;
long rc = ::sysconf( _SC_OPEN_MAX ) ;
if( rc > 0L )
n = static_cast<int>( rc ) ;
for( int fd = 0 ; fd < n ; fd++ )
{
if( !keep_stderr || fd != STDERR_FILENO )
::close( fd ) ;
}
}

View File

@ -0,0 +1,48 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdaemon_win32.cpp
//
#include "gdef.h"
#include "gdaemon.h"
//static
void G::Daemon::detach( const Path & )
{
}
//static
void G::Daemon::detach()
{
}
void G::Daemon::closeFiles( bool keep_stderr )
{
}
void G::Daemon::setUmask()
{
}
void G::Daemon::closeStderr()
{
}

266
src/glib/gdate.cpp Normal file
View File

@ -0,0 +1,266 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdate.cpp
//
#include "gdef.h"
#include "gdate.h"
#include "gdebug.h"
#include <sys/types.h>
#include <time.h>
//static
int G::Date::yearUpperLimit()
{
return 2035 ; // see mktime()
}
//static
int G::Date::yearLowerLimit()
{
return 1970 ; // see mktime()
}
G::Date::Date()
{
init( G::DateTime::utc(G::DateTime::now()) ) ;
}
G::Date::Date( G::DateTime::EpochTime t , const LocalTime & )
{
init( G::DateTime::local(t) ) ;
}
G::Date::Date( const G::DateTime::BrokenDownTime & tm )
{
init( tm ) ;
}
G::Date::Date( const LocalTime & )
{
init( G::DateTime::local(G::DateTime::now()) ) ;
}
G::Date::Date( int year , G::Date::Month month , int day_of_month )
{
G_ASSERT( year >= yearLowerLimit() ) ;
G_ASSERT( year <= yearUpperLimit() ) ;
G_ASSERT( day_of_month > 0 ) ;
G_ASSERT( day_of_month < 32 ) ;
G_ASSERT( month >= 1 ) ;
G_ASSERT( month <= 12 ) ;
m_year = year ;
m_month = month ;
m_day = day_of_month ;
m_weekday_set = false ;
}
void G::Date::init( const G::DateTime::BrokenDownTime & tm )
{
m_year = tm.tm_year + 1900 ;
m_month = tm.tm_mon + 1 ;
m_day = tm.tm_mday ;
m_weekday_set = false ;
m_weekday = sunday ;
}
std::string G::Date::string( Format ) const
{
std::stringstream ss ;
ss << m_year << "/" << m_month << "/" << m_day ;
return ss.str() ;
}
int G::Date::monthday() const
{
return m_day ;
}
std::string G::Date::monthdayString() const
{
std::stringstream ss ;
ss << m_day ;
return ss.str() ;
}
G::Date::Weekday G::Date::weekday() const
{
if( ! m_weekday_set )
{
G::DateTime::BrokenDownTime tm ;
tm.tm_year = m_year - 1900 ;
tm.tm_mon = m_month - 1 ;
tm.tm_mday = m_day ;
tm.tm_hour = 12 ;
tm.tm_min = 0 ;
tm.tm_sec = 0 ;
tm.tm_wday = 0 ; // ignored
tm.tm_yday = 0 ; // ignored
tm.tm_isdst = 0 ; // ignored
G::DateTime::BrokenDownTime out = G::DateTime::utc(G::DateTime::epochTime(tm)) ;
const_cast<Date*>(this)->m_weekday_set = true ;
const_cast<Date*>(this)->m_weekday = Weekday(out.tm_wday) ;
}
return m_weekday ;
}
std::string G::Date::weekdayString( bool brief ) const
{
if( weekday() == sunday ) return brief ? "Sun" : "Sunday" ;
if( weekday() == monday ) return brief ? "Mon" : "Monday" ;
if( weekday() == tuesday ) return brief ? "Tue" : "Tuesday" ;
if( weekday() == wednesday ) return brief ? "Wed" : "Wednesday" ;
if( weekday() == thursday ) return brief ? "Thu" : "Thursday" ;
if( weekday() == friday ) return brief ? "Fri" : "Friday" ;
if( weekday() == saturday ) return brief ? "Sat" : "Saturday" ;
return "" ;
}
G::Date::Month G::Date::month() const
{
return Month(m_month) ;
}
std::string G::Date::monthString( bool brief ) const
{
if( month() == january ) return brief ? "Jan" : "January" ;
if( month() == february ) return brief ? "Feb" : "February" ;
if( month() == march ) return brief ? "Mar" : "March" ;
if( month() == april ) return brief ? "Apr" : "April" ;
if( month() == may ) return brief ? "May" : "May" ;
if( month() == june ) return brief ? "Jun" : "June" ;
if( month() == july ) return brief ? "Jul" : "July" ;
if( month() == august ) return brief ? "Aug" : "August" ;
if( month() == september ) return brief ? "Sep" : "September" ;
if( month() == october ) return brief ? "Oct" : "October" ;
if( month() == november ) return brief ? "Nov" : "November" ;
if( month() == december ) return brief ? "Dec" : "December" ;
return "" ;
}
int G::Date::year() const
{
return m_year ;
}
std::string G::Date::yearString() const
{
std::stringstream ss ;
ss << m_year ;
return ss.str() ;
}
G::Date &G::Date::operator++()
{
++m_day ;
if( m_day == (lastDay(m_month,m_year)+1U) )
{
m_day = 1U ;
++m_month ;
if( m_month == 13U )
{
m_month = 1U ;
++m_year ;
}
}
if( m_weekday_set )
{
if( m_weekday == saturday )
m_weekday = sunday ;
else
m_weekday = Weekday(int(m_weekday)+1) ;
}
return *this ;
}
G::Date & G::Date::operator--()
{
if( m_day == 1U )
{
if( m_month == 1U )
{
m_year-- ;
m_month = 12U ;
}
else
{
m_month-- ;
}
m_day = lastDay( m_month , m_year ) ;
}
else
{
m_day-- ;
}
if( m_weekday_set )
{
if( m_weekday == sunday )
m_weekday = saturday ;
else
m_weekday = Weekday(int(m_weekday)-1) ;
}
return *this ;
}
//static
unsigned int G::Date::lastDay( unsigned int month , unsigned int year )
{
unsigned int end = 30U ;
if( month == 1U ||
month == 3U ||
month == 5U ||
month == 7U ||
month == 8U ||
month == 10U ||
month == 12U )
{
end = 31U ;
}
else if( month == 2U )
{
end = isLeapYear(year) ? 29U : 28U ;
}
return end ;
}
//static
bool G::Date::isLeapYear( unsigned int y )
{
return y >= 1800U && ( y % 400U == 0U || ( y % 100U != 0U && y % 4U == 0U ) ) ;
}
bool G::Date::operator==( const Date &other ) const
{
return
year() == other.year() &&
month() == other.month() &&
monthday() == other.monthday() ;
}
bool G::Date::operator!=( const Date &other ) const
{
return !( other == *this ) ;
}

134
src/glib/gdate.h Normal file
View File

@ -0,0 +1,134 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdate.h
//
#ifndef G_DATE_H
#define G_DATE_H
#include "gdef.h"
#include "gdatetime.h"
#include "gdebug.h"
#include <sys/types.h>
#include <time.h>
#include <string>
namespace G
{
class Date ;
} ;
// Class: G::Date
// Description: A date (dd/mm/yyyy) class.
//
class G::Date
{
public:
class LocalTime // An overload discriminator class for Date constructors.
{} ;
enum Weekday
{ sunday, monday, tuesday, wednesday, thursday, friday, saturday } ;
enum Month
{ january = 1 , february , march , april , may , june , july ,
august , september , october , november , december } ;
enum Format
{ yyyy_mm_dd_slash } ;
static int yearUpperLimit() ;
// Returns the smallest supported year value.
static int yearLowerLimit() ;
// Returns the largest supported year value.
Date() ;
// Default constructor the current date
// in the UTC timezone.
explicit Date( const LocalTime & ) ;
// Constructor for the current date
// in the local timezone.
explicit Date( const G::DateTime::BrokenDownTime & tm ) ;
// Constructor for the specified date.
explicit Date( G::DateTime::EpochTime t , const LocalTime & ) ;
// Constructor for the date in the local
// timezone as at the given epoch time.
Date( int year , Month month , int day_of_month ) ;
// Constructor for the specified date.
std::string string( Format format = yyyy_mm_dd_slash ) const ;
// Returns a string representation of the date.
Weekday weekday() const ;
// Returns the day of the week.
std::string weekdayString( bool brief = false ) const ;
// Returns a string representation of the day of the week.
int monthday() const ;
// Returns the day of the month.
std::string monthdayString() const ;
// Returns a string representation of the day of the month.
Month month() const ;
// Returns the month.
std::string monthString( bool brief = false ) const ;
// Returns the month as a string.
int year() const ;
// Returns the year.
std::string yearString() const ;
// Returns the year as a string.
Date &operator++() ;
// Increments the date by one day.
Date &operator--() ;
// Decrements the date by one day.
bool operator==( const Date &rhs ) const ;
// Comparison operator.
bool operator!=( const Date &rhs ) const ;
// Comparison operator.
private:
void init( const G::DateTime::BrokenDownTime & ) ;
static unsigned int lastDay( unsigned int month , unsigned int year ) ;
static bool isLeapYear( unsigned int y ) ;
private:
unsigned int m_day ;
unsigned int m_month ;
unsigned int m_year ;
bool m_weekday_set ;
Weekday m_weekday ;
} ;
#endif

103
src/glib/gdatetime.cpp Normal file
View File

@ -0,0 +1,103 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdatetime.cpp
//
#include "gdef.h"
#include "gdatetime.h"
#include "gstr.h"
#include "gassert.h"
#include <sstream>
const unsigned int minute = 60U ;
const unsigned int hour = 60U * minute ;
const unsigned int day = 24U * hour ;
G::DateTime::EpochTime G::DateTime::now()
{
return std::time(NULL) ;
}
G::DateTime::EpochTime G::DateTime::epochTime( const BrokenDownTime & bdt_in )
{
// get a rough starting point
BrokenDownTime bdt( bdt_in ) ;
EpochTime start = std::mktime( &bdt ) ; // localtime
// iterate over all timezones
const unsigned int delta = minute * 30U ;
for( EpochTime t = (start-day-delta) ; t <= (start+day+delta) ; t += delta )
{
if( equivalent( t , bdt_in ) )
return t ;
}
throw Error() ;
}
G::DateTime::BrokenDownTime G::DateTime::utc( EpochTime epoch_time )
{
BrokenDownTime result ;
G::DateTime::gmtime_r( &epoch_time , &result ) ;
return result ;
}
G::DateTime::BrokenDownTime G::DateTime::local( EpochTime epoch_time )
{
BrokenDownTime bdt_local ;
G::DateTime::localtime_r( &epoch_time , &bdt_local ) ;
return bdt_local ;
}
G::DateTime::Offset G::DateTime::offset( EpochTime utc )
{
BrokenDownTime bdt_local = local(utc) ;
EpochTime local = epochTime(bdt_local) ;
bool ahead = local >= utc ; // ie. east-of
unsigned int n = ahead ? (local-utc) : (utc-local) ;
return Offset( ahead , n ) ;
}
std::string G::DateTime::offsetString( Offset offset )
{
unsigned int hh = offset.second / 3600U ;
unsigned int mm = (offset.second / 60U) % 60 ;
std::stringstream ss ;
char sign = (offset.first || (hh==0&&mm==0)) ? '+' : '-' ;
ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ;
return ss.str() ;
}
bool G::DateTime::equivalent( EpochTime t , const BrokenDownTime & bdt_in )
{
BrokenDownTime bdt_test = utc(t) ;
return same( bdt_test , bdt_in ) ;
}
bool G::DateTime::same( const BrokenDownTime & bdt1 , const BrokenDownTime & bdt2 )
{
return
bdt1.tm_mday == bdt2.tm_mday &&
bdt1.tm_hour == bdt2.tm_hour &&
bdt1.tm_min == bdt2.tm_min ;
}

85
src/glib/gdatetime.h Normal file
View File

@ -0,0 +1,85 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdatetime.h
//
#ifndef G_DATE_TIME_H
#define G_DATE_TIME_H
#include <ctime>
#include "gdef.h"
#include "gexception.h"
#include <ctime>
#include <string>
namespace G
{
class DateTime ;
} ;
// Class: G::DateTime
// Description: A low-level static class used by Date and Time.
//
class G::DateTime
{
public:
G_EXCEPTION( Error , "date/time error" ) ;
typedef std::time_t EpochTime ;
typedef struct std::tm BrokenDownTime ;
typedef std::pair<bool,unsigned int> Offset ;
static EpochTime now() ;
// Returns the current epoch time.
static EpochTime epochTime( const BrokenDownTime & broken_down_time ) ;
// Converts from UTC broken-down-time to epoch time.
static BrokenDownTime utc( EpochTime epoch_time ) ;
// Converts from epoch time to UTC broken-down-time.
static BrokenDownTime local( EpochTime epoch_time ) ;
// Converts from epoch time to local broken-down-time.
static Offset offset( EpochTime epoch_time ) ;
// Returns the offset between UTC and localtime
// as at 'epoch_time'. The returned pair has
// 'first' set to true if localtime is
// ahead of (ie. east of) UTC.
//
// (Note that this may be a relatively expensive
// operation.)
static std::string offsetString( Offset offset ) ;
// Uses the five-character format "+/-hhmm".
// See also RFC2822.
static void tzset() ;
// Calls std::tzset() (portably). Used for testing.
private:
static bool equivalent( EpochTime , const BrokenDownTime & ) ;
static bool same( const BrokenDownTime & , const BrokenDownTime & ) ;
static std::tm * gmtime_r( const std::time_t * , std::tm * ) ;
static std::tm * localtime_r( const std::time_t * , std::tm * ) ;
DateTime() ;
} ;
#endif

View File

@ -0,0 +1,41 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdatetime_unix.cpp
//
#include "gdef.h"
#include "gdatetime.h"
void G::DateTime::tzset()
{
std::tzset() ;
}
std::tm * G::DateTime::gmtime_r( const std::time_t * t , std::tm * p )
{
return std::gmtime_r(t,p) ;
}
std::tm * G::DateTime::localtime_r( const std::time_t * t , std::tm * p )
{
return std::localtime_r(t,p) ;
}

View File

@ -0,0 +1,43 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdatetime_win32.cpp
//
#include "gdef.h"
#include "gdatetime.h"
void G::DateTime::tzset()
{
std::_tzset() ;
}
struct std::tm * G::DateTime::gmtime_r( const time_t * t , struct std::tm * p )
{
*p = *(std::gmtime(t)) ;
return p ;
}
struct std::tm * G::DateTime::localtime_r( const time_t * t , struct std::tm * p )
{
*p = *(std::localtime(t)) ;
return p ;
}

35
src/glib/gdebug.h Normal file
View File

@ -0,0 +1,35 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdebug.h
//
#ifndef G_DEBUG_H
#define G_DEBUG_H
#include "gdef.h"
#include "glogoutput.h"
#include "glog.h"
#include "gassert.h"
// backwards compatibility...
//typedef LogOutput GDebug ;
#endif

190
src/glib/gdef.h Normal file
View File

@ -0,0 +1,190 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdef.h
//
// This header is always the first header included in source
// files. It takes care of some portability issues, and
// is a good candidate for precompilation. It requires
// either G_UNIX or G_WIN32 to be defined on the compiler
// command line, although G_UNIX may also be inferred from
// autoconf's HAVE_CONFIG_H.
//
#ifndef G_DEF_H
#define G_DEF_H
// Autoconf stuff (mostly commented out)
//
#if HAVE_CONFIG_H
#if 0
#include <config.h>
#if HAVE_UNISTD_H
#include <sys/types.h>
#include <unistd.h>
#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#else
#define dirent direct
#if HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif
#if HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#if HAVE_NDIR_H
#include <ndir.h>
#endif
#endif
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#endif
#if ! defined( G_UNIX )
#define G_UNIX
#endif
#endif
// Check operating-system switches
//
#if !defined( G_WIN32 ) && !defined( G_UNIX )
#error invalid compilation switches
#endif
#if defined( G_WIN32 ) && defined( G_UNIX )
#error invalid compilation switches
#endif
// Define supplementary o/s compilation switches
//
#if defined( G_WIN32 ) && ! defined( G_WINDOWS )
#define G_WINDOWS
#endif
// Define the compiler and its capabilities
//
#if defined( _MSC_VER )
#define G_COMPILER_IS_MICROSOFT 1
// #define G_COMPILER_HAS_... 0
#endif
#if defined( __GNUC__ )
#define G_COMPILER_IS_GNU 1
// #define G_COMPILER_HAS_... 1
#endif
// Modify compiler error handling for system headers
//
#if defined( G_COMPILER_IS_MICROSOFT )
#pragma warning( disable : 4514 ) // don't reenable
#pragma warning( push , 3 )
#pragma warning( disable : 4201 )
#pragma warning( disable : 4514 ) // again
#pragma warning( disable : 4663 4018 4146 4018 )
#pragma warning( disable : 4244 4100 4512 4511 )
#endif
// Include main operating-system headers
//
#if defined( G_WINDOWS )
#include <windows.h>
#include <shellapi.h>
#else
#include <unistd.h>
#include <sys/stat.h>
#endif
// Restore complier error handling
//
#if defined( G_COMPILER_IS_MICROSOFT )
#pragma warning( default : 4201 )
#pragma warning( default : 4663 4018 4146 4018 )
#pragma warning( default : 4244 4100 4512 4511 )
#pragma warning( pop )
#endif
// Define Windows-style types (under Unix these
// are only used for unimplemented declarations)
//
#if ! defined( G_WINDOWS )
typedef unsigned char BOOL ;
typedef unsigned int HWND ;
typedef unsigned int HINSTANCE ;
typedef unsigned int HANDLE ;
#endif
// Include commonly-used system headers
//
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <xlocale>
#include <limits>
#include <memory>
#include <exception>
// Define fixed-size types
//
typedef unsigned long g_uint32_t ;
typedef unsigned short g_uint16_t ;
// Define short-name types
//
typedef unsigned char uchar_t ;
// Define missing standard types
//
#if defined( G_WINDOWS )
typedef int ssize_t ; // (should be in sys/types.h)
#endif
// STL portability macros
//
#if 1
#define GAllocator(T)
#define GLessAllocator(T1,T2)
#else
#define GAllocator(T) ,std::allocator<T>
#define GLessAllocator(T1,T2) ,std::allocator<T1>,std::less<T2>
#endif
// Modify compiler error handling
//
#if G_COMPILER_IS_MICROSOFT
#pragma warning( disable : 4100 ) // unused formal parameter
#pragma warning( disable : 4355 ) // 'this' in initialiser list
#pragma warning( disable : 4511 ) // cannot create default copy ctor
#pragma warning( disable : 4512 ) // cannot create default op=()
#pragma warning( disable : 4786 ) // truncation in debug info
#endif
#endif

75
src/glib/gdirectory.cpp Normal file
View File

@ -0,0 +1,75 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdirectory.cpp
//
#include "gdef.h"
#include "gdirectory.h"
#include "gfs.h"
#include "glog.h"
G::Directory::Directory() :
m_path(".")
{
}
G::Directory G::Directory::root()
{
std::string s ;
s.append( 1U , G::FileSystem::slash() ) ;
return Directory( s ) ;
}
G::Directory::Directory( const char * path ) :
m_path(path)
{
}
G::Directory::Directory( const std::string & path ) :
m_path(path)
{
}
G::Directory::Directory( const Path & path ) :
m_path(path)
{
}
G::Directory::~Directory()
{
}
G::Directory::Directory( const Directory &other ) :
m_path(other.m_path)
{
}
G::Directory &G::Directory::operator=( const Directory &rhs )
{
m_path = rhs.m_path ;
return *this ;
}
G::Path G::Directory::path() const
{
return m_path ;
}

137
src/glib/gdirectory.h Normal file
View File

@ -0,0 +1,137 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdirectory.h
//
#ifndef G_DIRECTORY_H
#define G_DIRECTORY_H
#include "gdef.h"
#include "gpath.h"
#include <string>
#include <sys/types.h>
namespace G
{
class DirectoryIteratorImp ;
class Directory ;
class DirectoryIterator ;
} ;
// Class: G::Directory
// Description: An encapsulation of a file system directory
// which allows for iterating through the set of contained
// files.
// See also: Path, FileSystem, File
//
class G::Directory
{
public:
Directory() ;
// Default constructor for the current directory.
explicit Directory( const char * path ) ;
// Constructor.
explicit Directory( const Path & path ) ;
// Constructor.
explicit Directory( const std::string & path ) ;
// Constructor.
virtual ~Directory() ;
// Virtual destructor.
bool valid( bool for_creating_files = false ) const ;
// Returns true if the object
// represents a valid directory.
//
// Does additional checks if the
// 'for-creating-files' parameter
// is true. But note that the
// answer is not definitive --
// file creation may fail, even
// if valid() returns true.
Path path() const ;
// Returns the directory's path.
Directory( const Directory &other ) ;
// Copy constructor.
Directory &operator=( const Directory & ) ;
// Assignment operator.
static Directory root() ;
// Returns a root directory object. For DOSy file
// systems this will not contain a drive part.
private:
Path m_path ;
} ;
// Class: G::DirectoryIterator
// Description: An iterator for Directory.
// The iteration model is
/// while(iter.more()) { (void)iter.file() ; }
//
class G::DirectoryIterator
{
public:
explicit DirectoryIterator( const Directory &dir , const char *wc = NULL ) ;
// Constructor taking a directory reference
// and an optional wildcard specification.
~DirectoryIterator() ;
// Destructor.
bool error() const ;
// Returns true on error. The caller should stop the iteration.
bool more() ;
// Returns true if more.
bool isDir() const ;
// Returns true if the current item is a directory.
std::string modificationTimeString() const ;
// Returns the last-modified time for the file in an undefined
// format -- used for comparison.
std::string sizeString() const ;
// Returns the file size as a decimal string. The value
// may be more than 32 bits. See also class Number.
Path filePath() const ;
// Returns the path of the current item.
Path fileName() const ;
// Returns the name of the current item.
private:
DirectoryIterator( const DirectoryIterator & ) ;
void operator=( const DirectoryIterator & ) ;
private:
DirectoryIteratorImp *m_imp ;
} ;
#endif

View File

@ -0,0 +1,241 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdirectory_unix.cpp
//
#include "gdef.h"
#include "gdirectory.h"
#include "gfs.h"
#include "gdebug.h"
#include "glog.h"
#include <unistd.h>
#include <dirent.h>
#include <glob.h>
namespace G
{
class DirectoryIteratorImp ;
} ;
bool G::Directory::valid( bool for_creation ) const
{
bool rc = true ;
struct stat statbuf ;
if( ::stat( m_path.pathCstr() , &statbuf ) )
{
rc = false ;
}
else if( !(statbuf.st_mode & S_IFDIR) )
{
rc = false ;
}
else
{
DIR * p = ::opendir( m_path.pathCstr() ) ;
if( p == NULL )
rc = false ;
else
::closedir( p ) ;
}
if( rc && for_creation )
{
// (see also GNU/Linux ::euidaccess())
if( 0 != ::access( m_path.pathCstr() , W_OK ) )
rc = false ;
}
G_DEBUG( "G::Directory::valid: \"" << m_path.str() << "\" is " << (rc?"":"not ") << "a directory" ) ;
return rc ;
}
// ===
// Class: G::DirectoryIteratorImp
// Description: A pimple-pattern implementation class for DirectoryIterator.
//
class G::DirectoryIteratorImp
{
private:
glob_t m_glob ;
Directory m_dir ;
bool m_first ;
size_t m_index ;
bool m_error ;
public:
DirectoryIteratorImp( const Directory &dir , const std::string & wildcard ) ;
~DirectoryIteratorImp() ;
bool isDir() const ;
bool more() ;
bool error() const ;
std::string modificationTimeString() const ;
std::string sizeString() const ;
Path filePath() const ;
Path fileName() const ;
private:
void operator=( const DirectoryIteratorImp & ) ;
DirectoryIteratorImp( const DirectoryIteratorImp & ) ;
static int onError( const char * path , int errno ) ;
} ;
// ===
G::DirectoryIterator::DirectoryIterator( const Directory &dir , const char *wc )
{
m_imp = new DirectoryIteratorImp( dir , wc ) ;
}
bool G::DirectoryIterator::error() const
{
return m_imp->error() ;
}
bool G::DirectoryIterator::more()
{
return m_imp->more() ;
}
G::Path G::DirectoryIterator::filePath() const
{
return m_imp->filePath() ;
}
G::Path G::DirectoryIterator::fileName() const
{
return m_imp->fileName() ;
}
bool G::DirectoryIterator::isDir() const
{
return m_imp->isDir() ;
}
std::string G::DirectoryIterator::modificationTimeString() const
{
return m_imp->modificationTimeString() ;
}
std::string G::DirectoryIterator::sizeString() const
{
return m_imp->sizeString() ;
}
G::DirectoryIterator::~DirectoryIterator()
{
delete m_imp ;
}
// ===
//static
int G::DirectoryIteratorImp::onError( const char * , int )
{
const int abort = 1 ;
return abort ;
}
G::DirectoryIteratorImp::DirectoryIteratorImp( const Directory &dir ,
const std::string & wildcard ) :
m_dir(dir) ,
m_first(true) ,
m_index(0U) ,
m_error(false)
{
m_glob.gl_pathc = 0 ;
m_glob.gl_pathv = NULL ;
Path wild_path( m_dir.path() ) ;
wild_path.pathAppend( wildcard.empty() ? std::string("*") : wildcard ) ;
G_DEBUG( "G::DirectoryIteratorImp::ctor: glob(\"" << wild_path << "\")" ) ;
int flags = 0 | GLOB_ERR ;
int error = ::glob( wild_path.pathCstr() , flags , onError , &m_glob ) ;
if( error )
{
G_DEBUG( "G::DirectoryIteratorImp::ctor: glob() error: " << error ) ;
m_error = true ;
}
else
{
G_ASSERT( m_glob.gl_pathv != NULL ) ;
G_ASSERT( m_glob.gl_pathc == 0 || m_glob.gl_pathv[0] != NULL ) ;
}
}
bool G::DirectoryIteratorImp::error() const
{
return m_error ;
}
bool G::DirectoryIteratorImp::more()
{
if( m_error )
return false ;
if( ! m_first )
m_index++ ;
m_first = false ;
if( m_index >= m_glob.gl_pathc )
return false ;
return true ;
}
G::Path G::DirectoryIteratorImp::filePath() const
{
G_ASSERT( m_index < m_glob.gl_pathc ) ;
G_ASSERT( m_glob.gl_pathv != NULL ) ;
G_ASSERT( m_glob.gl_pathv[m_index] != NULL ) ;
const char * file_path = m_glob.gl_pathv[m_index] ;
return Path( file_path ) ;
}
G::Path G::DirectoryIteratorImp::fileName() const
{
return Path( filePath().basename() ) ;
}
bool G::DirectoryIteratorImp::isDir() const
{
Directory dir( filePath().str() ) ;
return dir.valid() ;
}
G::DirectoryIteratorImp::~DirectoryIteratorImp()
{
if( ! m_error )
::globfree( &m_glob ) ;
}
std::string G::DirectoryIteratorImp::modificationTimeString() const
{
return std::string() ; // for now
}
std::string G::DirectoryIteratorImp::sizeString() const
{
return std::string("0") ; // for now
}

View File

@ -0,0 +1,302 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gdirectory_win32.cpp
//
#include "gdef.h"
#include "gdirectory.h"
#include "gfs.h"
#include "gnumber.h"
#include "gdebug.h"
#include "glog.h"
namespace G
{
class DirectoryIteratorImp ;
} ;
bool G::Directory::valid( bool for_creation ) const
{
DWORD attributes = ::GetFileAttributes( m_path.pathCstr() ) ;
if( attributes == 0xFFFFFFFF )
{
(void)::GetLastError() ;
return false ;
}
return ( attributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ;
}
// ===
// Class: G::DirectoryIteratorImp
// Description: A pimple-pattern implementation class for DirectoryIterator.
//
class G::DirectoryIteratorImp
{
private:
WIN32_FIND_DATA m_context ;
HANDLE m_handle ;
Directory m_dir ;
bool m_error ;
bool m_first ;
bool m_special ; // if wc = ".." -- FindFirstFile returns ".."'s proper name -- this class returns ".."
public:
DirectoryIteratorImp( const Directory &dir , const char *wildcard ) ;
~DirectoryIteratorImp() ;
bool isDir() const ;
bool more() ;
bool error() const ;
std::string modificationTimeString() const ;
std::string sizeString() const ;
Path filePath() const ;
Path fileName() const ;
private:
void operator=( const DirectoryIteratorImp & ) ;
DirectoryIteratorImp( const DirectoryIteratorImp & ) ;
} ;
// ===
G::DirectoryIterator::DirectoryIterator( const Directory &dir , const char *wc )
{
m_imp = new DirectoryIteratorImp( dir , wc ) ;
}
bool G::DirectoryIterator::error() const
{
return m_imp->error() ;
}
bool G::DirectoryIterator::more()
{
return m_imp->more() ;
}
G::Path G::DirectoryIterator::filePath() const
{
return m_imp->filePath() ;
}
G::Path G::DirectoryIterator::fileName() const
{
return m_imp->fileName() ;
}
bool G::DirectoryIterator::isDir() const
{
return m_imp->isDir() ;
}
std::string G::DirectoryIterator::modificationTimeString() const
{
return m_imp->modificationTimeString() ;
}
std::string G::DirectoryIterator::sizeString() const
{
return m_imp->sizeString() ;
}
G::DirectoryIterator::~DirectoryIterator()
{
delete m_imp ;
}
// ===
G::DirectoryIteratorImp::DirectoryIteratorImp( const Directory & dir ,
const char *wildcard ) :
m_dir(dir) ,
m_error(false) ,
m_first(true) ,
m_special(false)
{
if( wildcard == NULL )
{
wildcard = "*.*" ;
}
else if( std::string(wildcard) == ".." )
{
G_DEBUG( "DirectoryIteratorImp: special work-round for .." ) ;
m_special = true ;
return ;
}
Path wild_path( m_dir.path() ) ;
wild_path.pathAppend( wildcard ) ;
G_DEBUG( "G::DirectoryIteratorImp::ctor: FindFirstFile(\""
<< wild_path << "\")" ) ;
m_handle = ::FindFirstFile( wild_path.pathCstr() , &m_context ) ;
if( m_handle == INVALID_HANDLE_VALUE )
{
DWORD err = ::GetLastError() ;
if( err == ERROR_FILE_NOT_FOUND )
{
G_DEBUG( "G::DirectoryIteratorImp::ctor: none" ) ;
}
else
{
m_error = true ;
G_DEBUG( "G::DirectoryIteratorImp::ctor: error " << err << " for "
<< wild_path ) ;
}
}
else
{
G_DEBUG( "G::DirectoryIteratorImp::ctor: first \""
<< m_context.cFileName << "\"" ) ;
}
}
bool G::DirectoryIteratorImp::error() const
{
return m_error ;
}
bool G::DirectoryIteratorImp::more()
{
if( m_special )
{
bool rc = m_first ;
m_first = false ;
return rc ;
}
if( m_handle == INVALID_HANDLE_VALUE )
return false ;
if( m_first )
{
m_first = false ;
if( ::strcmp(m_context.cFileName,".") &&
::strcmp(m_context.cFileName,"..") )
return true ;
G_DEBUG( "G::DirectoryIteratorImp::more: ignoring " << m_context.cFileName);
}
for(;;)
{
bool rc = ::FindNextFile( m_handle , &m_context ) != 0 ;
if( !rc )
{
DWORD err = ::GetLastError() ;
if( err == ERROR_NO_MORE_FILES )
{
G_DEBUG( "G::DirectoryIteratorImp::more: no more" ) ;
}
else
{
G_DEBUG( "G::DirectoryIteratorImp::more: error" ) ;
m_error = true ;
}
::FindClose( m_handle ) ;
m_handle = INVALID_HANDLE_VALUE ;
return false ;
}
// go round again if . or ..
if( ::strcmp(m_context.cFileName,".") &&
::strcmp(m_context.cFileName,"..") )
{
G_DEBUG( "G::DirectoryIteratorImp::more: " << m_context.cFileName ) ;
break ;
}
else
{
G_DEBUG( "G::DirectoryIteratorImp::more: ignoring " << m_context.cFileName ) ;
}
}
return true ;
}
G::Path G::DirectoryIteratorImp::filePath() const
{
Path file_path( m_dir.path() ) ;
if( m_special )
{
file_path.pathAppend( ".." ) ;
}
else
{
G_ASSERT( m_handle != INVALID_HANDLE_VALUE ) ;
file_path.pathAppend( m_context.cFileName ) ;
}
return file_path ;
}
G::Path G::DirectoryIteratorImp::fileName() const
{
if( m_special )
{
return Path("..") ;
}
else
{
G_ASSERT( m_handle != INVALID_HANDLE_VALUE ) ;
return Path(m_context.cFileName) ;
}
}
bool G::DirectoryIteratorImp::isDir() const
{
return m_special || m_context.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;
}
G::DirectoryIteratorImp::~DirectoryIteratorImp()
{
if( m_handle != INVALID_HANDLE_VALUE )
::FindClose( m_handle ) ;
}
std::string G::DirectoryIteratorImp::modificationTimeString() const
{
if( m_special )
{
// ??
G_ASSERT( !"modificationTimeString() not fully implemented for .." ) ;
return std::string() ;
}
char buffer[50U] ;
::sprintf( buffer , "%lX%08lX" ,
(unsigned long)m_context.ftLastWriteTime.dwHighDateTime ,
(unsigned long)m_context.ftLastWriteTime.dwLowDateTime ) ;
return std::string(buffer) ;
}
std::string G::DirectoryIteratorImp::sizeString() const
{
if( m_special )
{
return std::string( "0" ) ;
}
Number size( m_context.nFileSizeHigh , m_context.nFileSizeLow ) ;
return size.displayString() ;
}

82
src/glib/gexception.cpp Normal file
View File

@ -0,0 +1,82 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gexception.cpp
//
#include "gdef.h"
#include "gexception.h"
G::Exception::Exception()
{
}
G::Exception::Exception( const char * what ) :
m_what(what?what:"")
{
}
G::Exception::Exception( const std::string & what ) :
m_what(what)
{
}
G::Exception::~Exception()
{
}
const char * G::Exception::what() const
{
return m_what.c_str() ;
}
void G::Exception::append( const char * more )
{
if( more != NULL && *more != '\0' )
{
m_what += ": " ;
m_what += more ;
}
}
void G::Exception::append( const std::string & more )
{
m_what += ": " ;
m_what += more ;
}
void G::Exception::append( std::ostream & stream )
{
std::stringstream * ss = dynamic_cast<std::stringstream*>(&stream) ;
if( ss != NULL )
{
append( ss->str() ) ;
}
}
void G::Exception::prepend( const char * context )
{
if( context != NULL && *context != '\0' )
{
m_what = std::string(context) + ": " + m_what ;
}
}

89
src/glib/gexception.h Normal file
View File

@ -0,0 +1,89 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gexception.h
//
#ifndef G_EXCEPTION_H
#define G_EXCEPTION_H
#include "gdef.h"
#include <string>
#include <iostream>
namespace G
{
class Exception ;
} ;
// Class: G::Exception
// Description: A general-purpose exception class derived from std::exception
// and containing a std::string.
//
class G::Exception : public std::exception
{
protected:
std::string m_what ;
public:
Exception() ;
// Default constructor.
explicit Exception( const char * what ) ;
// Constructor.
explicit Exception( const std::string & what ) ;
// Constructor.
virtual ~Exception() ;
// Destructor.
virtual const char * what() const ;
// Override from std::exception.
void prepend( const char * context ) ;
// Prepends context to the what string.
// Inserts a separator as needed.
void append( const char * more ) ;
// Appends 'more' to the what string.
// Inserts a separator as needed.
void append( const std::string & more ) ;
// Appends 'more' to the what string.
// Inserts a separator as needed.
void append( std::ostream & s ) ;
// Appends the contents of the given std::stringstream
// (sic) to the what string. Does nothing if the
// dynamic type of 's' is not a std::stringstream.
// Inserts a separator as needed.
//
// This method allows a derived-class exception
// to be constructed and thrown on one
// line using iostream formatting.
// Eg. throw Error( std::stringstream() << a << b ) ;
} ;
#define G_EXCEPTION( class_name , description ) class class_name : public G::Exception { public: class_name() { m_what = description ; } public: explicit class_name ( std::ostream & stream ) { m_what = description ; append(stream) ; } public: explicit class_name( const char * more ) { m_what = description ; append(more) ; } public: explicit class_name( const std::string & more ) { m_what = description ; append(more) ; } }
#define G_EXCEPTION_ G_EXCEPTION
#endif

85
src/glib/gfile.cpp Normal file
View File

@ -0,0 +1,85 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfile.cpp
//
#include "gdef.h"
#include "gfile.h"
#include "glog.h"
#include <iostream>
#include <cstdio>
bool G::File::remove( const Path & path , const G::File::NoThrow & )
{
bool rc = 0 == std::remove( path.pathCstr() ) ;
G_DEBUG( "G::File::remove: \"" << path << "\": success=" << rc ) ;
return rc ;
}
void G::File::remove( const Path & path )
{
if( 0 != std::remove( path.pathCstr() ) )
{
//int error = std::errno ;
throw CannotRemove( path.str() ) ;
}
G_DEBUG( "G::File::remove: \"" << path << "\"" ) ;
}
bool G::File::rename( const Path & from , const Path & to , const NoThrow & )
{
bool rc = 0 == std::rename( from.pathCstr() , to.pathCstr() ) ;
G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\": success=" << rc ) ;
return rc ;
}
void G::File::rename( const Path & from , const Path & to )
{
if( 0 != std::rename( from.pathCstr() , to.pathCstr() ) )
{
//int error = std::errno ;
throw CannotRename( from.str() ) ;
}
G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\"" ) ;
}
void G::File::copy( const Path & from , const Path & to )
{
if( !copy(from,to,NoThrow()) )
throw CannotCopy( from.str() ) ;
}
bool G::File::copy( const Path & from , const Path & to , const NoThrow & )
{
std::ifstream in( from.str().c_str() , std::ios_base::binary | std::ios_base::in ) ;
std::ofstream out( to.str().c_str() , std::ios_base::binary | std::ios_base::out | std::ios_base::trunc ) ;
char c ;
while( in.get(c) )
out << c ;
return in.eof() && out.good() ;
}
void G::File::mkdir( const Path & dir )
{
if( ! mkdir( dir , NoThrow() ) )
throw CannotMkdir( dir.str() ) ;
}

76
src/glib/gfile.h Normal file
View File

@ -0,0 +1,76 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfile.h
//
#ifndef G_FILE_H
#define G_FILE_H
#include "gdef.h"
#include "gpath.h"
#include "gexception.h"
#include <cstdio> // std::remove()
namespace G
{
class File ;
} ;
// Class: G::File
// Description: A simple static class for dealing with files.
// See also: Path, FileSystem, Directory
//
class G::File
{
public:
G_EXCEPTION( CannotRemove , "cannot delete file" ) ;
G_EXCEPTION( CannotRename , "cannot rename file" ) ;
G_EXCEPTION( CannotCopy , "cannot copy file" ) ;
G_EXCEPTION( CannotMkdir , "cannot mkdir" ) ;
class NoThrow // An overload discriminator class for File methods.
{} ;
static bool remove( const Path & path , const NoThrow & ) ;
// Deletes the file or directory. Returns false on error.
static void remove( const Path & path ) ;
// Deletes the file or directory. Throws an exception on error.
static bool rename( const Path & from , const Path & to , const NoThrow & ) ;
// Renames the file. Returns false on error.
static void rename( const Path & from , const Path & to ) ;
// Renames the file.
static bool copy( const Path & from , const Path & to , const NoThrow & ) ;
// Copies a file. Returns false on error.
static void copy( const Path & from , const Path & to ) ;
// Copies a file.
static bool mkdir( const Path & dir , const NoThrow & ) ;
// Creates a directory. Returns false on error.
static void mkdir( const Path & dir ) ;
// Creates a directory.
} ;
#endif

32
src/glib/gfile_unix.cpp Normal file
View File

@ -0,0 +1,32 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfile_unix.cpp
//
#include "gdef.h"
#include "gfile.h"
#include <sys/stat.h>
bool G::File::mkdir( const Path & dir , const NoThrow & )
{
return 0 == ::mkdir( dir.str().c_str() , S_IRUSR | S_IWUSR | S_IXUSR ) ;
}

33
src/glib/gfile_win32.cpp Normal file
View File

@ -0,0 +1,33 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfile_win32.cpp
//
#include "gdef.h"
#include "gfile.h"
#include <sys/stat.h>
#include <direct.h>
bool G::File::mkdir( const Path & dir , const NoThrow & )
{
return 0 == ::_mkdir( dir.str().c_str() ) ;
}

52
src/glib/gfs.h Normal file
View File

@ -0,0 +1,52 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfs.h
//
#ifndef G_FS_H
#define G_FS_H
#include "gdef.h"
namespace G
{
class FileSystem ;
} ;
// Class: G::FileSystem
// Description: Provides information about the
// local operating system's file system
// conventions.
// See also: Path, File
//
class G::FileSystem
{
public:
static const char *nullDevice() ;
static bool allowsSpaces() ;
static char slash() ; // separator
static char nonSlash() ; // to be converted to slash()
static bool caseSensitive() ;
static bool usesDriveLetters() ; // <drive>:
static bool leadingDoubleSlash() ; // win32 network paths
} ;
#endif

61
src/glib/gfs_unix.cpp Normal file
View File

@ -0,0 +1,61 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfs_unix.cpp
//
#include "gdef.h"
#include "gfs.h"
const char *G::FileSystem::nullDevice()
{
return "/dev/null" ;
}
char G::FileSystem::slash()
{
return '/' ;
}
char G::FileSystem::nonSlash()
{
return '\\' ;
}
bool G::FileSystem::allowsSpaces()
{
return false ;
}
bool G::FileSystem::caseSensitive()
{
return true ;
}
bool G::FileSystem::usesDriveLetters()
{
return false ;
}
bool G::FileSystem::leadingDoubleSlash()
{
return false ;
}

60
src/glib/gfs_win32.cpp Normal file
View File

@ -0,0 +1,60 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gfs_win32.cpp
//
#include "gdef.h"
#include "gfs.h"
const char *G::FileSystem::nullDevice()
{
return "NUL" ;
}
char G::FileSystem::slash()
{
return '\\' ;
}
char G::FileSystem::nonSlash()
{
return '/' ;
}
bool G::FileSystem::allowsSpaces()
{
return true ; // (but false for win16)
}
bool G::FileSystem::caseSensitive()
{
return false ;
}
bool G::FileSystem::usesDriveLetters()
{
return true ;
}
bool G::FileSystem::leadingDoubleSlash()
{
return true ; // (but false for win16)
}

500
src/glib/ggetopt.cpp Normal file
View File

@ -0,0 +1,500 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// ggetopt.cpp
//
#include "gdef.h"
#include "glog.h"
#include "gstrings.h"
#include "gstr.h"
#include "ggetopt.h"
#include "gassert.h"
#include "gdebug.h"
static void GetOpt__pushBack( void * out , const std::string & s )
{
reinterpret_cast<G::GetOpt::StringArray*>(out)->push_back(s) ;
}
G::GetOpt::GetOpt( const Arg & args_in , const std::string & spec ,
char sep_major , char sep_minor , char escape ) :
m_args(args_in)
{
parseSpec( spec , sep_major , sep_minor , escape ) ;
size_t n = parseArgs( args_in ) ;
remove( n ) ;
}
void G::GetOpt::parseSpec( const std::string & spec , char sep_major , char sep_minor , char escape )
{
if( spec.find(sep_minor) == std::string::npos )
parseOldSpec( spec ) ;
else
parseNewSpec( spec , sep_major , sep_minor , escape ) ;
}
void G::GetOpt::parseOldSpec( const std::string & spec )
{
for( size_t i = 0U ; i < spec.length() ; i++ )
{
char c = spec.at(i) ;
if( c != ':' )
{
bool valued = (i+1U) < spec.length() && spec.at(i+1U) == ':' ;
addSpec( c , valued ) ;
}
}
}
void G::GetOpt::parseNewSpec( const std::string & spec , char sep_major ,
char sep_minor , char escape )
{
Strings outer ;
std::string ws_major( 1U , sep_major ) ;
G::Str::splitIntoFields( spec , outer , ws_major , escape , false ) ;
for( Strings::iterator p = outer.begin() ; p != outer.end() ; ++p )
{
StringArray inner ;
std::string ws_minor( 1U , sep_minor ) ;
G::Str::splitIntoFields( *p , inner , ws_minor , escape ) ;
if( inner.size() != 5U )
throw InvalidSpecification(std::stringstream() << "\"" << *p << "\" (" << ws_minor << ")") ;
bool valued = G::Str::toUInt( inner[3U] ) != 0U ;
addSpec( inner[0U].at(0U) , inner[1U] , inner[2U] , valued , inner[4U] ) ;
}
}
void G::GetOpt::addSpec( char c , bool valued )
{
addSpec( c , std::string() , std::string() , valued , std::string() ) ;
}
void G::GetOpt::addSpec( char c , const std::string & name , const std::string & description ,
bool valued , const std::string & value_description )
{
if( c == '\0' )
throw InvalidSpecification() ;
std::pair<SwitchSpecMap::iterator,bool> rc =
m_spec_map.insert( std::make_pair(c,SwitchSpec(c,name,description,valued,value_description)) ) ;
if( ! rc.second )
throw InvalidSpecification("duplication") ;
}
bool G::GetOpt::valued( const std::string & name ) const
{
return valued(key(name)) ;
}
bool G::GetOpt::valued( char c ) const
{
SwitchSpecMap::const_iterator p = m_spec_map.find( c ) ;
if( p == m_spec_map.end() )
return false ;
else
return (*p).second.valued ;
}
char G::GetOpt::key( const std::string & name ) const
{
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{
if( (*p).second.name == name )
{
return (*p).first ;
}
}
G_DEBUG( "G::GetOpt::key: " << name << " not found" ) ;
return '\0' ;
}
//static
size_t G::GetOpt::wrapDefault()
{
return 79U ;
}
//static
size_t G::GetOpt::widthLimit( size_t w )
{
return (w != 0U && w < 50U) ? 50U : w ;
}
void G::GetOpt::showUsage( std::ostream & stream , const std::string & exe , const std::string & args ,
size_t tab_stop , size_t width ) const
{
stream
<< usageSummary(exe,args,width) << std::endl
<< usageHelp(tab_stop,width) ;
}
std::string G::GetOpt::usageSummary( const std::string & exe , const std::string & args , size_t width ) const
{
std::string s = std::string("usage: ") + exe + " " + usageSummarySwitches() + args ;
if( width != 0U )
{
return G::Str::wrap( s , "" , " " , widthLimit(width) ) ;
}
else
{
return s ;
}
}
std::string G::GetOpt::usageSummarySwitches() const
{
return usageSummaryPartOne() + usageSummaryPartTwo() ;
}
std::string G::GetOpt::usageSummaryPartOne() const
{
// summarise the single-character switches, excluding those which take a value
std::stringstream ss ;
bool first = true ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{
if( ! (*p).second.valued )
{
if( first )
ss << "[-" ;
first = false ;
ss << (*p).first ;
}
}
std::string s = ss.str() ;
if( s.length() ) s.append( "] " ) ;
return s ;
}
std::string G::GetOpt::usageSummaryPartTwo() const
{
std::stringstream ss ;
const char * sep = "" ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{
ss << sep << "[" ;
if( (*p).second.name.length() )
{
ss << "--" << (*p).second.name ;
}
else
{
ss << "-" << (*p).first ;
}
if( (*p).second.valued )
{
std::string vd = (*p).second.value_description ;
if( vd.empty() ) vd = "value" ;
ss << " <" << vd << ">" ;
}
ss << "]" ;
sep = " " ;
}
return ss.str() ;
}
std::string G::GetOpt::usageHelp( size_t tab_stop , size_t width ) const
{
return usageHelpCore( " " , tab_stop , widthLimit(width) ) ;
}
std::string G::GetOpt::usageHelpCore( const std::string & prefix , size_t tab_stop , size_t width ) const
{
std::string result ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{
std::string line( prefix ) ;
line.append( "-" ) ;
line.append( 1U , (*p).first ) ;
if( (*p).second.name.length() )
{
line.append( ",--" ) ;
line.append( (*p).second.name ) ;
}
if( (*p).second.valued )
{
std::string vd = (*p).second.value_description ;
if( vd.empty() ) vd = "value" ;
line.append( " <" ) ;
line.append( vd ) ;
line.append( ">" ) ;
}
line.append( 1U , ' ' ) ;
if( line.length() < tab_stop )
line.append( tab_stop-line.length() , ' ' ) ;
line.append( (*p).second.description ) ;
if( width )
{
std::string indent( tab_stop , ' ' ) ;
line = G::Str::wrap( line , "" , indent , width ) ;
}
result.append( line ) ;
}
return result ;
}
size_t G::GetOpt::parseArgs( const Arg & args_in )
{
size_t i = 1U ;
for( ; i < args_in.c() ; i++ )
{
const std::string & arg = args_in.v(i) ;
if( arg == "--" )
{
i++ ;
break ;
}
if( isSwitchSet(arg) )
{
for( size_t n = 1U ; n < arg.length() ; n++ )
processSwitch( arg.at(n) ) ;
}
else if( isOldSwitch(arg) )
{
char c = arg.at(1U) ;
if( valued(c) && (i+1U) >= args_in.c() )
errorNoValue( c ) ;
else if( valued(c) )
processSwitch( c , args_in.v(++i) ) ;
else
processSwitch( c ) ;
}
else if( isNewSwitch(arg) )
{
std::string name = arg.substr( 2U ) ;
if( valued(name) && (i+1U) >= args_in.c() )
errorNoValue( name ) ;
else if( valued(name) )
processSwitch( name , args_in.v(++i) ) ;
else
processSwitch( name ) ;
}
else
{
break ;
}
}
i-- ;
G_DEBUG( "G::GetOpt::parseArgs: removing " << i << " switch args" ) ;
return i ;
}
bool G::GetOpt::isOldSwitch( const std::string & arg ) const
{
return
( arg.length() > 1U && arg.at(0U) == '-' ) &&
! isNewSwitch( arg ) ;
}
bool G::GetOpt::isNewSwitch( const std::string & arg ) const
{
return arg.length() > 2U && arg.at(0U) == '-' && arg.at(1U) == '-' ;
}
bool G::GetOpt::isSwitchSet( const std::string & arg ) const
{
return isOldSwitch(arg) && arg.length() > 2U ;
}
void G::GetOpt::errorNoValue( char c )
{
std::string e("no value supplied for -") ;
e.append( 1U , c ) ;
m_errors.push_back( e ) ;
}
void G::GetOpt::errorNoValue( const std::string & name )
{
std::string e("no value supplied for --") ;
e.append( name ) ;
m_errors.push_back( e ) ;
}
void G::GetOpt::errorUnknownSwitch( char c )
{
std::string e("invalid switch: -") ;
e.append( 1U , c ) ;
m_errors.push_back( e ) ;
}
void G::GetOpt::errorUnknownSwitch( const std::string & name )
{
std::string e("invalid switch: --") ;
e.append( name ) ;
m_errors.push_back( e ) ;
}
void G::GetOpt::processSwitch( const std::string & name )
{
if( !valid(name) )
{
errorUnknownSwitch( name ) ;
return ;
}
char c = key(name) ;
if( valued(c) )
{
errorNoValue( name ) ;
return ;
}
m_map.insert( std::make_pair(c,std::make_pair(false,std::string())) ) ;
}
void G::GetOpt::processSwitch( const std::string & name , const std::string & value )
{
if( !valid(name) )
{
errorUnknownSwitch( name ) ;
return ;
}
char c = key(name) ;
m_map.insert( std::make_pair(c,std::make_pair(true,value)) ) ;
}
void G::GetOpt::processSwitch( char c )
{
if( !valid(c) )
{
errorUnknownSwitch( c ) ;
return ;
}
if( valued(c) )
{
errorNoValue( c ) ;
return ;
}
m_map.insert( std::make_pair(c,std::make_pair(false,std::string())) ) ;
}
void G::GetOpt::processSwitch( char c , const std::string & value )
{
if( !valid(c) )
errorUnknownSwitch( c ) ;
m_map.insert( std::make_pair(c,std::make_pair(true,value)) ) ;
}
G::Strings G::GetOpt::errorList() const
{
return m_errors ;
}
bool G::GetOpt::contains( char c ) const
{
SwitchMap::const_iterator p = m_map.find( c ) ;
return p != m_map.end() ;
}
bool G::GetOpt::contains( const std::string & name ) const
{
char c = key(name) ;
SwitchMap::const_iterator p = m_map.find( c ) ;
return p != m_map.end() ;
}
std::string G::GetOpt::value( char c ) const
{
G_ASSERT( contains(c) ) ;
SwitchMap::const_iterator p = m_map.find( c ) ;
Value value_pair = (*p).second ;
return value_pair.second ;
}
std::string G::GetOpt::value( const std::string & name ) const
{
return value( key(name) ) ;
}
G::Arg G::GetOpt::args() const
{
return m_args ;
}
void G::GetOpt::show( std::ostream &stream , std::string prefix ) const
{
for( SwitchMap::const_iterator p = m_map.begin() ; p != m_map.end() ; ++p )
{
char c = (*p).first ;
Value v = (*p).second ;
SwitchSpecMap::const_iterator q = m_spec_map.find( c ) ;
std::string name ;
if( q != m_spec_map.end() )
name = (*q).second.name ;
stream << prefix << "--" << name ;
if( v.first )
stream << " = \"" << v.second << "\"" ;
stream << std::endl ;
}
}
bool G::GetOpt::hasErrors() const
{
return m_errors.size() != 0U ;
}
void G::GetOpt::showErrors( std::ostream &stream , std::string prefix_1 ,
std::string prefix_2 ) const
{
if( m_errors.size() != 0U )
{
for( Strings::const_iterator p = m_errors.begin() ;
p != m_errors.end() ; ++p )
{
stream << prefix_1 << prefix_2 << *p << std::endl ;
}
}
}
void G::GetOpt::remove( size_t n )
{
if( n != 0U )
{
m_args.removeAt(1U,n-1U) ;
}
}
bool G::GetOpt::valid( const std::string & name ) const
{
return valid( key(name) ) ;
}
bool G::GetOpt::valid( char c ) const
{
return m_spec_map.find( c ) != m_spec_map.end() ;
}

175
src/glib/ggetopt.h Normal file
View File

@ -0,0 +1,175 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// ggetopt.h
//
#ifndef G_GETOPT_H
#define G_GETOPT_H
#include "gdef.h"
#include "garg.h"
#include "gstrings.h"
#include "gexception.h"
#include <string>
#include <list>
#include <map>
namespace G
{
class GetOpt ;
} ;
// Class: G::GetOpt
// Description: A command line switch parser.
//
class G::GetOpt
{
public:
typedef std::vector<std::string GAllocator(std::string) > StringArray ;
G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ;
GetOpt( const Arg & arg , const std::string & spec ,
char sep_major = '|' , char sep_minor = '/' , char escape = '\\' ) ;
// Constructor taking a Arg reference and a
// specification string. Supports old-fashioned
// getopt specification strings such as "p:dv", and
// also new-stye specifications like
// "p/port/port number/1|d/debug/show debug/0|v/verbose/show more/0".
// In the new-style specification each switch definition
// is made up of the following...
// <single-character-switch-letter>
// <multi-character-switch-name>
// <switch-description>
// <value-type> -- 0 is none, and 1 is a string
// <value-description>
Arg args() const ;
// Returns all the non-switch command-line arguments.
Strings errorList() const ;
// Returns the list of errors.
static size_t wrapDefault() ;
// Returns a default word-wrapping width.
std::string usageSummary( const std::string & exe , const std::string & args ,
size_t wrap_width = wrapDefault() ) const ;
// Returns a one-line usage summary, as
// "usage: <exe> <usageSummarySwitches()> <args>"
std::string usageSummarySwitches() const ;
// Returns the one-line summary of switches. Does _not_
// include the usual "usage: <exe>" prefix
// or non-switch arguments.
std::string usageHelp( size_t tab_stop = 30U , size_t wrap_width = wrapDefault() ) const ;
// Returns a multi-line string giving help on each switch.
void showUsage( std::ostream & stream , const std::string & exe ,
const std::string & args , size_t tab_stop = 30U ,
size_t wrap_width = wrapDefault() ) const ;
// Streams out multi-line usage text using
// usageSummary() and usageHelp(). Does nothing
// about non-switch arguments.
bool hasErrors() const ;
// Returns true if there are errors.
void showErrors( std::ostream & stream , std::string prefix_1 ,
std::string prefix_2 = std::string(": ") ) const ;
// A convenience function which streams out each errorList()
// item to the given stream, prefixed with the given
// prefix(es). The two prefixes are simply concatenated.
void show( std::ostream & stream , std::string prefix ) const ;
// For debugging.
bool contains( char switch_letter ) const ;
// Returns true if the command line contains
// the given switch.
bool contains( const std::string & switch_name ) const ;
// Returns true if the command line contains
// the given switch.
std::string value( const std::string & switch_name ) const ;
// Returns the value related to the given
// value-based switch.
std::string value( char switch_letter ) const ;
// Returns the value related to the given
// value-based switch.
private:
struct SwitchSpec
{
char c ;
std::string name ;
std::string description ;
bool valued ;
std::string value_description ;
SwitchSpec(char c_,const std::string &name_,const std::string &description_,
bool v_,const std::string &vd_) :
c(c_) , name(name_) , description(description_) ,
valued(v_) , value_description(vd_) {}
} ;
typedef std::map<char,SwitchSpec GLessAllocator(char,SwitchSpec) > SwitchSpecMap ;
typedef std::pair<bool,std::string> Value ;
typedef std::map<char,Value GLessAllocator(char,Value) > SwitchMap ;
void operator=( const GetOpt & ) ;
GetOpt( const GetOpt & ) ;
void parseSpec( const std::string & spec , char , char , char ) ;
void parseOldSpec( const std::string & spec ) ;
void parseNewSpec( const std::string & spec , char , char , char ) ;
void addSpec( char c , bool valued ) ;
void addSpec( char c , const std::string & name , const std::string & , bool valued , const std::string & ) ;
size_t parseArgs( const Arg & args_in ) ;
bool isOldSwitch( const std::string & arg ) const ;
bool isNewSwitch( const std::string & arg ) const ;
bool isSwitchSet( const std::string & arg ) const ;
void processSwitch( char c ) ;
void processSwitch( char c , const std::string & value ) ;
void processSwitch( const std::string & s ) ;
void processSwitch( const std::string & s , const std::string & value ) ;
bool valued( char c ) const ;
bool valued( const std::string & ) const ;
void errorNoValue( char c ) ;
void errorNoValue( const std::string & ) ;
void errorUnknownSwitch( char c ) ;
void errorUnknownSwitch( const std::string & ) ;
char key( const std::string & s ) const ;
void remove( size_t n ) ;
bool valid( const std::string & ) const ;
bool valid( char c ) const ;
std::string usageSummaryPartOne() const ;
std::string usageSummaryPartTwo() const ;
std::string usageHelpCore( const std::string & , size_t , size_t ) const ;
static size_t widthLimit( size_t ) ;
private:
SwitchSpecMap m_spec_map ;
SwitchMap m_map ;
Strings m_errors ;
Arg m_args ;
} ;
#endif

124
src/glib/glog.cpp Normal file
View File

@ -0,0 +1,124 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glog.cpp
//
#include "gdef.h"
#include "glog.h"
#include "glogoutput.h"
namespace G
{
class LogImp ;
} ;
// Class: LogImp
// Description: An implementation class used by Log.
//
class G::LogImp
{
public:
static std::stringstream &s() ;
static bool active() ;
static void empty() ;
static const char *m_file ;
static int m_line ;
static std::stringstream *m_ss ;
} ;
const char *G::LogImp::m_file = NULL ;
std::stringstream *G::LogImp::m_ss = NULL ;
int G::LogImp::m_line = 0 ;
std::stringstream &G::LogImp::s()
{
if( m_ss == NULL )
m_ss = new std::stringstream ;
return *m_ss ;
}
void G::LogImp::empty()
{
delete m_ss ;
m_ss = NULL ;
m_ss = new std::stringstream ;
}
bool G::LogImp::active()
{
LogOutput * output = G::LogOutput::instance() ;
if( output == NULL )
{
return false ;
}
else
{
bool a = output->enable(true) ;
output->enable(a) ;
return a ;
}
}
// ===
G::Log::End G::Log::end( G::Log::Severity severity )
{
return End(severity) ;
}
G::Log::Stream & G::Log::stream()
{
if( G::LogImp::active() )
{
return G::LogImp::s() ;
}
else
{
static char buffer[3] ;
static std::stringstream dummy( buffer , sizeof(buffer) ) ;
return dummy ;
}
}
void G::Log::onEnd( G::Log::Severity severity )
{
if( G::LogImp::active() )
{
G::LogOutput::output( severity , G::LogImp::m_file , G::LogImp::m_line ,
G::LogImp::s().str().c_str() ) ;
// empty the stream
G::LogImp::empty() ;
}
G::LogImp::m_file = NULL ;
G::LogImp::m_line = 0 ;
}
void G::Log::setFile( const char *file )
{
G::LogImp::m_file = file ;
}
void G::Log::setLine( int line )
{
G::LogImp::m_line = line ;
}

130
src/glib/glog.h Normal file
View File

@ -0,0 +1,130 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glog.h
//
#ifndef G_LOG_H
#define G_LOG_H
#include "gdef.h"
namespace G
{
class Log ;
} ;
// Class: G::Log
// Description: A static class for doing iostream-based logging.
// The G_LOG/G_DEBUG/G_WARNING/G_ERROR macros are provided as a
// convenient way of using this interface.
//
// Usage:
/// G::Log::stream()
/// << G::Log::Line(__FILE__,__LINE__)
/// << a << b << G::Log::end() ;
// or
/// G_LOG( a << b ) ;
//
// See also: LogOutput
//
class G::Log
{
public:
typedef std::ostream Stream ;
enum Severity { s_Log , s_Debug , s_Warning , s_Error , s_Assertion } ;
struct End // A private implementation class for Log. An End object from end() must be streamed out to flush a spooled message.
{ Severity m_s ; End(Severity s) : m_s(s) {} } ;
class Line // A class for adding line number information to the Log output.
{ public: Line( const char *file , int line ) ; } ;
static End end( Severity severity ) ;
// Returns an End object which can be used to close off a quantum
// of logging. (The End::op<<() function calls G::Log::onEnd().)
static Stream &stream() ;
// Returns a stream for streaming messages into.
static void onEnd( Severity s ) ;
// A pseudo-private method used by ::operator<<(End).
private:
friend class G::Log::Line ;
static void setFile( const char *file ) ;
static void setLine( int line ) ;
Log() ;
} ;
namespace G
{
inline
std::ostream &operator<<( std::ostream &stream ,
const G::Log::Line & )
{
return stream ;
}
} ;
namespace G
{
inline
std::ostream &operator<<( std::ostream &stream ,
const G::Log::End &end )
{
G::Log::onEnd( end.m_s ) ;
return stream ;
}
} ;
namespace G
{
inline
G::Log::Line::Line( const char *file , int line )
{
G::Log::setFile( file ) ;
G::Log::setLine( line ) ;
}
} ;
// Macros: G_LOG, G_DEBUG, G_WARNING, G_ERROR
// The debug macro is for debugging during development. The log macro
// is used for progress logging, typically in long-lived server processes.
// The warning and error macros are used for error warning/error messages.
// In programs where logging can be disabled completely (see LogOutput)
// then warning/error messages should also get raised by some another
// independent means.
//
#define G_LOG_OUTPUT( expr , severity ) { G::Log::stream() << G::Log::Line(__FILE__,__LINE__) << expr << G::Log::end(severity) ; }
#if defined(_DEBUG) && ! defined(G_NO_DEBUG)
#define G_DEBUG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Debug )
#else
#define G_DEBUG( expr )
#endif
#if ! defined(G_NO_LOG)
#define G_LOG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Log )
#else
#define G_LOG( expr )
#endif
#define G_WARNING( expr ) G_LOG_OUTPUT( expr , G::Log::s_Warning )
#define G_ERROR( expr ) G_LOG_OUTPUT( expr , G::Log::s_Error )
#endif

178
src/glib/glogoutput.cpp Normal file
View File

@ -0,0 +1,178 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glogoutput.cpp
//
#include "gdef.h"
#include "glogoutput.h"
#include <cstdlib>
#include <cstring>
G::LogOutput *G::LogOutput::m_this = NULL ;
G::LogOutput::LogOutput( bool enabled , bool verbose ) :
m_enabled(enabled) ,
m_verbose(verbose) ,
m_syslog(false)
{
if( m_this == NULL )
m_this = this ;
}
G::LogOutput::~LogOutput()
{
if( m_this == this )
m_this = NULL ;
}
bool G::LogOutput::enable( bool enabled )
{
bool was_enabled = m_enabled ;
m_enabled = enabled ;
return was_enabled ;
}
//static
void G::LogOutput::itoa( char *out , unsigned int n )
{
n = n % 1000000U ;
if( n == 0U )
{
out[0] = '0' ;
out[1] = '\0' ;
}
else
{
char buffer[15] ;
char *p = buffer + sizeof(buffer) - 1 ;
*p-- = '\0' ;
for( ; n > 0U ; --p )
{
*p = '0' + (n % 10U) ;
n /= 10U ;
}
::strcpy( out , p+1 ) ;
}
}
//static
void G::LogOutput::output( G::Log::Severity severity , const char *text )
{
if( m_this != NULL )
{
if( severity != G::Log::s_Debug || m_this->m_verbose )
{
m_this->rawOutput( severity , text ? text : "" ) ;
if( text && text[0] && text[std::strlen(text)-1] != '\n' )
m_this->rawOutput( severity , "\n" ) ;
}
}
}
//static
void G::LogOutput::output( G::Log::Severity severity , const char *file, unsigned line, const char *text )
{
file = file ? file : "" ;
text = text ? text : "" ;
// no-op if disabled
if( m_this == NULL || !m_this->m_enabled )
return ;
char buffer[500] ;
buffer[0] = '\0' ;
if( severity == G::Log::s_Debug )
fileAndLine( buffer , sizeof(buffer) , file , line ) ;
std::strncat( buffer + std::strlen(buffer) , text , sizeof(buffer) - 1 - std::strlen(buffer) ) ;
output( severity , buffer ) ;
}
G::LogOutput *G::LogOutput::instance()
{
return m_this ;
}
void G::LogOutput::onAssert()
{
// no-op
}
//static
void G::LogOutput::fileAndLine( char *buffer , size_t size , const char *file , int line )
{
const char *forward = ::strrchr( file , '/' ) ;
const char *back = ::strrchr( file , '\\' ) ;
const char *last = forward > back ? forward : back ;
const char *basename = last ? (last+1) : file ;
std::strncat( buffer+std::strlen(buffer) , basename , size-std::strlen(buffer)-1 ) ;
std::strncat( buffer+std::strlen(buffer) , "(" , size-std::strlen(buffer)-1 ) ;
char b[15] ;
itoa( b , line ) ;
std::strncat( buffer+std::strlen(buffer) , b , size-std::strlen(buffer)-1 ) ;
std::strncat( buffer+std::strlen(buffer) , "): " , size-std::strlen(buffer)-1 ) ;
}
void G::LogOutput::assertion( const char *file , unsigned line , bool test , const char *test_string )
{
if( !test )
{
char buffer[100] ;
std::strcpy( buffer , "Assertion error: " ) ;
size_t size = sizeof(buffer) - 10 ; // -10 for luck
if( file )
{
fileAndLine( buffer , size , file , line ) ;
}
if( test_string )
{
std::strncat( buffer+std::strlen(buffer) , test_string , size-std::strlen(buffer)-1);
}
if( instance() )
{
// forward to derived classes -- these
// overrides may safely re-enter this method --
// all code in this class is re-entrant
//
instance()->onAssert() ;
}
output( G::Log::s_Assertion , buffer ) ;
halt() ;
}
}
//static
void G::LogOutput::halt()
{
abort() ;
}
void G::LogOutput::syslog( SyslogFacility facility )
{
m_syslog = true ;
m_facility = facility ;
}

113
src/glib/glogoutput.h Normal file
View File

@ -0,0 +1,113 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glogoutput.h
//
#ifndef G_LOG_OUTPUT_H
#define G_LOG_OUTPUT_H
#include "gdef.h"
#include "glog.h"
namespace G
{
class LogOutput ;
} ;
// Class: G::LogOutput
// Description: Controls and implements low-level logging output, as used by the Log interface.
// Applications should normally instantiate a LogOutput object in main() to enable
// log output.
// See also: Log
//
class G::LogOutput
{
public:
enum SyslogFacility { User , Daemon , Mail , Cron } ; // etc.
explicit LogOutput( bool logging_enabled , bool verbose = true ) ;
// Constructor. If there is no LogOutput object,
// or if 'logging_enabled' is false, then there is no
// output of any sort. If both parameters are true
// then debug messages will be generated in addition
// to the log/warning/error messages (as long
// as it was compiled in).
//
// More than one LogOutput object may be created, but
// only the first one controls output.
virtual ~LogOutput() ;
// Destructor.
virtual void rawOutput( G::Log::Severity s , const char *string ) ;
// Overridable. Used to do the final message
// output (with OutputDebugString() or stderr).
static LogOutput *instance() ;
// Returns a pointer to the controlling
// LogOutput object. Returns NULL if none.
bool enable( bool debug_enabled = true ) ;
// Enables or disables debug output.
// Returns the previous setting.
void syslog() ;
// Enables logging to the syslog system under Unix.
void syslog( SyslogFacility facility ) ;
// Enables logging to the syslog system under Unix,
// using the specified facility.
static void output( G::Log::Severity s , const char *raw_output ) ;
// Generates debug output if there is an extant
// LogOutput object which is enabled. Uses rawOutput().
static void output( G::Log::Severity s , const char *file , unsigned line , const char *text ) ;
// Generates debug output if there is an extant
// LogOutput object which is enabled. Uses rawOutput().
static void assertion( const char *file , unsigned line , bool test , const char *test_string ) ;
// Makes an assertion check (regardless of any LogOutput
// object). Calls output() if the 'file' parameter is
// not null.
virtual void onAssert() ;
// Called during an assertion failure. This allows
// Windows applications to stop timers etc. which
// cause reentrancy problems and infinitely recursive
// dialog box creation.
private:
LogOutput( const LogOutput & ) ;
void operator=( const LogOutput & ) ;
static void itoa( char *out , unsigned int ) ;
static void fileAndLine( char * , size_t , const char * , int ) ;
static void halt() ;
private:
static LogOutput *m_this ;
bool m_enabled ;
bool m_verbose ;
bool m_syslog ;
SyslogFacility m_facility ;
} ;
#endif

View File

@ -0,0 +1,64 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glogoutput_unix.cpp
//
#include "gdef.h"
#include "glogoutput.h"
#include <syslog.h>
#include <iostream>
namespace
{
int mode( G::LogOutput::SyslogFacility facility , G::Log::Severity severity )
{
int m = 0 ;
if( facility == G::LogOutput::User ) m |= LOG_USER ;
else if( facility == G::LogOutput::Daemon ) m |= LOG_DAEMON ;
else if( facility == G::LogOutput::Mail ) m |= LOG_MAIL ;
else if( facility == G::LogOutput::Cron ) m |= LOG_CRON ;
// etc...
if( severity == G::Log::s_Warning ) m |= LOG_WARNING ;
else if( severity == G::Log::s_Error ) m |= LOG_ERR ;
else if( severity == G::Log::s_Log ) m |= LOG_INFO ;
else m |= LOG_CRIT ;
return m ;
}
} ;
void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
{
if( severity != G::Log::s_Debug && m_syslog && !(message[0]=='\n'&&message[1]=='\0') )
{
::syslog( mode(m_facility,severity) , "%s" , message ) ;
}
std::cerr << message ;
std::cerr.flush() ;
}
void G::LogOutput::syslog()
{
syslog( User ) ;
}

View File

@ -0,0 +1,60 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// glogoutput_win32.cpp
//
#include "gdef.h"
#include "glogoutput.h"
#include <cstdlib> // getenv
#include <cstring> // strlen
namespace std { using ::getenv ; using ::strlen ; } ;
void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
{
std::cerr << message ;
std::cerr.flush() ;
if( std::getenv("GLOGOUTPUT_DEBUGGER") != NULL )
{
::OutputDebugString( message ) ;
}
static bool first = true ;
static const char * filename = NULL ;
if( first )
{
first = false ;
const char * key = "GLOGOUTPUT_FILE" ;
filename = std::getenv(key) ;
}
if( filename != NULL && *filename != '\0' )
{
static std::ofstream file( filename ) ;
file << message ;
file.flush() ;
}
}
void G::LogOutput::syslog()
{
}

60
src/glib/gmemory.h Normal file
View File

@ -0,0 +1,60 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gmemory.h
//
#ifndef G_MEMORY_H
#define G_MEMORY_H
#include "gdef.h"
#include <memory>
// Template function: operator<<=
// Description: A fix for the problem of resetting
// an auto_ptr portably. MSVC6.0 does not have a reset
// method, and GCC has a non-const assignment
// operators. This means that the MSVC code and
// the gcc code for resetting an auto_ptr are
// radically different. This operator hides
// those differences.
//
template <class T>
void operator<<=( std::auto_ptr<T> & ap , T * p )
{
#ifdef G_WINDOWS
ap = std::auto_ptr<T>( p ) ;
#else
ap.reset( p ) ;
#endif
}
// Template function: operator<<=
// Description: A version for null pointers.
//
template <class T>
void operator<<=( std::auto_ptr<T> & ap , int null_pointer )
{
//operator<<=<T>( ap , (T*)(0) ) ;
T * p = 0 ;
ap <<= p ;
}
#endif

545
src/glib/gnumber.cpp Normal file
View File

@ -0,0 +1,545 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gnumber.cc
//
#include "gdef.h"
#include "gnumber.h"
#include "gdebug.h"
#include <stdio.h>
#include <math.h>
#include <limits.h>
const g_uint32_t bit31 = 0x80000000L ;
inline bool msb( g_uint32_t n )
{
return !!( n & bit31 ) ;
} ;
G::Number::~Number()
{
}
G::Number::Number() :
m_high(0) ,
m_low(0)
{
}
G::Number::Number( g_uint32_t n32 ) :
m_low(n32) ,
m_high(0)
{
}
G::Number::Number( g_uint32_t high , g_uint32_t low ) :
m_low(low) ,
m_high(high)
{
}
G::Number::Number( const Number &other )
{
m_low = other.m_low ;
m_high = other.m_high ;
}
G::Number &G::Number::operator=( const Number &other )
{
m_low = other.m_low ;
m_high = other.m_high ;
return *this ;
}
bool G::Number::big() const
{
return m_high != 0 ;
}
bool G::Number::big( long* ) const
{
// optimise for the common case
if( sizeof(long) <= sizeof(g_uint32_t) )
{
return m_high != 0 || m_low > LONG_MAX ;
}
// or more generally...
Number n = LONG_MAX ;
return (*this) > n ;
}
bool G::Number::big( unsigned long* ) const
{
if( sizeof(unsigned long) <= sizeof(g_uint32_t) )
{
return m_high != 0 || m_low > ULONG_MAX ;
}
Number n = ULONG_MAX ;
return (*this) > n ;
}
g_uint32_t G::Number::value() const
{
if( big() )
{
g_uint32_t rc = 0 ;
rc = ~rc ;
return rc ;
}
return m_low ;
}
unsigned long G::Number::value( unsigned long *p )
{
if( big((unsigned long*)0) )
{
if( p != NULL ) *p = ULONG_MAX ;
return ULONG_MAX ;
}
unsigned long ul = m_high ;
ul <<= 32 ; // ignore warnings -- this is in case sizeof(long) > 32
ul |= m_low ;
if( p != NULL ) *p = ul ;
return ul ;
}
G::Number::operator double()
{
double d = m_high ;
d *= static_cast<double>(0x10000L) ; // <<=16
d *= static_cast<double>(0x10000L) ; // <<=16
d += m_low ;
return d ;
}
G::Number::operator unsigned long()
{
return value( (unsigned long *)0 ) ;
}
long G::Number::value( long *p )
{
if( big((long*)0) )
{
if( p != NULL ) *p = LONG_MAX ;
return LONG_MAX ;
}
long l = m_high ;
l <<= 32 ; // ignore warnings -- this is in case sizeof(long) > 32
l |= m_low ;
if( p != NULL ) *p = l ;
return l ;
}
G::Number &G::Number::to48bits()
{
m_high &= 0xffff ;
return *this ;
}
g_uint32_t G::Number::high() const
{
return m_high ;
}
g_uint32_t G::Number::low() const
{
return m_low ;
}
void G::Number::lshift( unsigned places )
{
if( places == 0 )
{
}
else if( places < 32 )
{
m_high <<= places ;
m_high |= (m_low >> (32-places)) ;
m_low <<= places ;
}
else if( places == 32 )
{
lshift32() ;
}
else if( places < 64 )
{
m_high = m_low ;
m_low = 0 ;
m_high <<= ( places - 32 ) ;
}
else
{
m_high = m_low = 0 ;
}
}
void G::Number::lshift32()
{
m_high = m_low ;
m_low = 0 ;
}
void G::Number::rshift( unsigned places )
{
if( places == 0 )
{
}
else if( places < 32 )
{
m_low >>= places ;
m_low |= (m_high << (32-places)) ;
m_high >>= places ;
}
else if( places == 32 )
{
rshift32() ;
}
else if( places < 64 )
{
m_low = m_high ;
m_high = 0 ;
m_low >>= ( places - 32 ) ;
}
else
{
m_high = m_low = 0 ;
}
}
void G::Number::rshift32()
{
m_low = m_high ;
m_high = 0 ;
}
G::Number G::Number::operator++(int)
{
Number old = (*this) ;
++(*this) ;
return old ;
}
G::Number G::Number::operator--(int)
{
Number old = (*this) ;
--(*this) ;
return old ;
}
G::Number &G::Number::operator++()
{
m_low++ ;
if( m_low == 0 )
m_high++ ;
return *this ;
}
G::Number &G::Number::operator--()
{
if( m_low == 0 )
m_high-- ;
m_low-- ;
return *this ;
}
G::Number G::Number::operator+( const Number &other ) const
{
Number result = (*this) ;
result += other ;
return result ;
}
G::Number G::Number::operator-( const Number &other ) const
{
Number result = (*this) ;
result -= other ;
return result ;
}
G::Number G::Number::operator*( const Number &other ) const
{
Number result = (*this) ;
result *= other ;
return result ;
}
G::Number G::Number::operator/( g_uint16_t divisor ) const
{
Number result = (*this) ;
result /= divisor ;
return result ;
}
G::Number &G::Number::operator-=( const Number &other )
{
if( &other == this )
{
m_high = m_low = 0 ;
return *this ;
}
// create two's complement of other..
Number copy = other ;
copy.m_high = ~copy.m_high ;
copy.m_low = ~copy.m_low ;
++copy ;
// ..and add
(*this) += copy ;
return *this ;
}
G::Number &G::Number::operator+=( const Number &other )
{
if( &other == this )
{
m_high <<= 1 ;
m_high += msb( m_low ) ;
m_low <<= 1 ;
return *this ;
}
bool a = msb( m_low ) ;
bool b = msb( other.m_low ) ;
g_uint32_t new_low = m_low + other.m_low ;
bool c = msb( new_low ) ;
m_low = new_low ;
bool carry = ( a && b ) | ( (a ^ b) && !c ) ;
m_high += other.m_high ;
if( carry )
m_high++ ;
return *this ;
}
G::Number &G::Number::operator/=( g_uint16_t divisor )
{
Number remainder ;
Number quotient ;
divide16( (*this) , divisor , quotient , remainder ) ;
(*this) = quotient ;
return *this ;
}
G::Number &G::Number::operator%=( g_uint16_t divisor )
{
Number remainder ;
Number quotient ;
divide16( (*this) , divisor , quotient , remainder ) ;
(*this) = remainder ;
return *this ;
}
void G::Number::divide16( const Number &const_dividend , g_uint16_t divisor , Number &quotient , Number &remainder )
{
// division is complicated by the need for a double-width
// accumulator ie. an accumulator double the width of the
// divisor -- since we restrict ourselves to using built-in
// types of 32 bits (for portability) this divisor is limited
// to 16 bits. Full 64/64 bit division must be built using
// this 64/16 bit division and a 128-bit accumulator.
// the algorithm is basic long division -- consider dividing
// a four digit (16-bit) hex number by a one-digit (4-bit)
// hex number -- then scale the algorithm up to 64/16 bits.
G_ASSERT( divisor != 0 ) ;
quotient = 0 ;
remainder = 0 ;
Number accumulator = 0 ;
Number dividend = const_dividend ;
for( size_t i = 0 ; i < 4 ; i++ )
{
// shift the dividend into the accumulator
accumulator <<= 16 ;
accumulator.m_low |= (dividend.m_high >> 16) ;
dividend <<= 16 ;
G_ASSERT( accumulator.m_high == 0 ) ; // assert 32 bit accumulator
// shift the partial quotient into the full quotient
quotient <<= 16 ;
quotient.m_low |= (accumulator.m_low / divisor) ;
G_ASSERT( ((accumulator.m_low / divisor) >>16) == 0 ) ; // assert 16 bit partial quotient
// set the accumulator to the partial remainder
accumulator = (accumulator.m_low % divisor) ;
G_ASSERT( (accumulator.m_low >> 16) == 0 ) ; // assert 16 bit accumulator
}
remainder = accumulator ;
}
G::Number &G::Number::operator*=( const Number &other )
{
if( &other == this )
{
Number copy( other ) ;
operator*=( copy ) ;
return *this ;
}
// 16 * 16 -> 32
if( m_high == 0 && other.m_high == 0 &&
m_low <= 0xffff && other.m_low <= 0xffff )
{
m_low *= other.m_low ;
}
// 32 * 32 -> 64
else if( m_high == 0 && other.m_high == 0 )
{
// four 16-bit numbers
Number a( (m_low >> 16) & 0xffff ) ;
Number b( m_low & 0xffff ) ;
Number c( (other.m_low >> 16) & 0xffff ) ;
Number d( other.m_low & 0xffff ) ;
// one 32-bit partial product
Number bd = b ; bd *= d ;
// two 48-bit partial products
Number cb = c ; cb *= b ; cb.lshift(16) ;
Number ad = a ; ad *= d ; ad.lshift(16) ;
// one 64-bit partial product
Number ac = a ; ac *= c ; ac.lshift32() ;
// 64-bit product
Number product = bd ;
product += cb ;
product += ad ;
product += ac ;
m_low = product.m_low ;
m_high = product.m_high ;
}
// 64 * 64 -> 64
else
{
// four 32-bit numbers
Number a( m_high ) ;
Number b( m_low ) ;
Number c( other.m_high ) ;
Number d( other.m_low ) ;
// three 64-bit partial products
Number bd = b ; bd *= d ;
Number cb = c ; cb *= b ; cb.lshift32() ;
Number ad = a ; ad *= d ; ad.lshift32() ;
// 64-bit product
Number product = bd ;
product += cb ;
product += ad ;
m_low = product.m_low ;
m_high = product.m_high ;
}
return *this ;
}
bool G::Number::operator==( const Number &other ) const
{
return m_high == other.m_high && m_low == other.m_low ;
}
bool G::Number::operator!=( const Number &other ) const
{
return !( *this == other ) ;
}
bool G::Number::operator<( const Number &other ) const
{
if( m_high == other.m_high )
return m_low < other.m_low ;
else
return m_high < other.m_high ;
}
bool G::Number::operator<=( const Number &other ) const
{
return ( *this < other ) || ( *this == other ) ;
}
bool G::Number::operator>( const Number &other ) const
{
return !( *this <= other ) ;
}
bool G::Number::operator>=( const Number &other ) const
{
return !( *this < other ) ;
}
G::Number &G::Number::operator|=( const Number &other )
{
m_high |= other.m_high ;
m_low |= other.m_low ;
return *this ;
}
G::Number &G::Number::operator<<=( unsigned places )
{
lshift( places ) ;
return *this ;
}
G::Number &G::Number::operator>>=( unsigned places )
{
rshift( places ) ;
return *this ;
}
std::string G::Number::displayString() const
{
std::stringstream ss ;
if( m_high != 0 )
{
ss << m_high ;
ss.width( 8U ) ;
ss << m_low ;
}
else
{
ss << m_low ;
}
return ss.str() ;
}
namespace G
{
std::ostream & operator<<( std::ostream & stream , const Number n )
{
stream << n.displayString() ;
return stream ;
}
} ;

213
src/glib/gnumber.h Normal file
View File

@ -0,0 +1,213 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gnumber.h
//
#ifndef G_NUMBER_H
#define G_NUMBER_H
#include "gdef.h"
#include <string>
namespace G
{
class Number ;
} ;
// Class: G::Number
// Description: A Number object represents an unsigned integer
// of up to 64 bits. The implementation is very old and not complete.
//
// See also: a64l(3c), LONGLONG, uint64_t, u_longlong_t
//
class G::Number
{
public:
Number() ;
// Default constructor. The value is set to zero.
Number( g_uint32_t n32 ) ;
// Constructor taking one 32-bit argument.
Number( g_uint32_t high , g_uint32_t low ) ;
// Constructor taking two 32-bit arguments.
Number( const Number &other ) ;
// Copy constructor.
~Number() ;
// Destructor.
g_uint32_t value() const ;
// Returns the numeric value. Returns the maximum
// 32-bit value if the value is too big for a g_uint32_t.
// See big(). (This behaviour is generally preferable to
// truncating the value to 32 bits since a very big
// number can suddenly become a small number. Other
// member functions are available to do truncation.)
unsigned long value( unsigned long *ulp ) ;
// Returns (by value and reference) the value
// as an unsigned long. The value returned is
// ULONG_MAX if the number is too big for an
// unsigned long. See big(unsigned long*) and
// operator unsigned long().
long value( long *lp ) ;
// Returns (by value and reference) the value
// as a long integer. The value returned is
// LONG_MAX if the number is too big for a long.
// See big(long*).
operator unsigned long() ;
// Cast operator. The value returned is ULONG_MAX if
// the number is too big for an unsigned long. See
// big(unsigned long*) and value(unsigned long*).
operator double() ;
// Cast operator returning a double precision
// floating point value.
bool big() const ;
// Returns true if the number is bigger than
// 32 bits. See value().
bool big( long *dummy ) const ;
// Returns true if the number is too big
// for a long. See operator long().
// The dummy parameter is ignored.
bool big( unsigned long *dummy ) const ;
// Returns true if the number is too big
// for an unsigned long. See operator
// unsigned long(). The dummy parameter
// is ignored.
Number &operator=( const Number &other ) ;
// Assignment operator.
Number &to48bits() ;
// Truncates the value to 48 bits. The top 16 bits
// are zeroed.
g_uint32_t high() const ;
// Returns the most significant 32 bits.
g_uint32_t low() const ;
// Returns the least significant 32 bits.
Number operator+ ( const Number &addend ) const ;
// Addition operator.
Number &operator+=( const Number &addend ) ;
// Self-addition operator.
Number operator- ( const Number &subtrahend ) const ;
// Subtraction operator.
Number &operator-=( const Number &subtrahend ) ;
// Self-subtraction operator.
Number operator* ( const Number &multiplicand ) const ;
// Multiplcation operator.
Number &operator*=( const Number &multiplicand ) ;
// Self-multiplication operator.
Number operator/ ( g_uint16_t divisor ) const ;
// Division operator.
Number &operator/=( g_uint16_t divisor ) ;
// Self-division operator.
Number operator% ( g_uint16_t divisor ) const ;
// Modulo operator.
Number &operator%=( g_uint16_t divisor ) ;
// Self-modulo operator.
Number &operator|=( const Number &other ) ;
// Bitwise OR operator.
void lshift( unsigned places ) ;
// Left-shifts this number by the given number of bits.
void lshift32() ;
// Left-shifts this number 32 bits.
void rshift( unsigned places ) ;
// Right-shifts this number by the given number of bits.
void rshift32() ;
// Right-shifts this number 32 bits.
Number &operator<<=( unsigned places ) ;
// Left-shift operator.
Number &operator>>=( unsigned places ) ;
// Right-shift operator.
Number operator++(int) ;
// Post-increment operator.
Number operator--(int) ;
// Post-decrement operator.
Number &operator++() ;
// Pre-increment operator.
Number &operator--() ;
// Post-increment operator.
bool operator==( const Number &other ) const ;
// Equality comparison operator.
bool operator!=( const Number &other ) const ;
// Inequality comparison operator.
bool operator<( const Number &other ) const ;
// Less-than comparison operator.
bool operator<=( const Number &other ) const ;
// Less-than-or-equal comparison operator.
bool operator>( const Number &other ) const ;
// Greater-than comparison operator.
bool operator>=( const Number &other ) const ;
// Greater-than-or-equal comparison operator.
friend std::ostream &operator<<( std::ostream &stream , const Number n ) ;
// Global function which streams out a Number object.
std::string displayString() const ;
// Returns a printable string representation.
private:
static void divide16( const Number &dividend , g_uint16_t divisor , Number &quot , Number &rem ) ;
private:
g_uint32_t m_high ;
g_uint32_t m_low ;
} ;
#endif

424
src/glib/gpath.cpp Normal file
View File

@ -0,0 +1,424 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gpath.cpp
//
#include "gdef.h"
#include "gpath.h"
#include "gfs.h"
#include "gstr.h"
#include "gdebug.h"
#include "glog.h"
#include <cstring>
G::Path::Path() :
m_dot(NULL)
{
validate( "d-ctor" ) ;
}
G::Path::~Path()
{
}
G::Path::Path( const std::string & path )
{
set( path ) ;
validate( "c-ctor" ) ;
}
G::Path::Path( const char *path )
{
set( std::string(path) ) ;
validate( "ctor(cstr)" ) ;
}
G::Path::Path( const Path & other )
{
set( other.str() ) ;
validate( "ctor(Path)" ) ;
}
void G::Path::set( const std::string & path )
{
clear() ;
m_str = path ;
normalise() ;
}
void G::Path::clear()
{
m_extension = "" ;
m_str = "" ;
m_dot = NULL ;
}
void G::Path::normalise()
{
char ns[2] ; char s[2] ; char ss[3] ;
s[0] = ss[0] = ss[1] = FileSystem::slash() ;
ns[0] = FileSystem::nonSlash() ;
ns[1] = s[1] = ss[2] = '\0' ;
// normalise spaces
if( !FileSystem::allowsSpaces() )
Str::replaceAll( m_str , " " , "" ) ;
// normalise alternate (non) slash characters
Str::replaceAll( m_str , ns , s ) ;
// save leading double-slashes
bool has_leading_double_slash =
FileSystem::leadingDoubleSlash() &&
m_str.find( ss ) == 0U ;
// normalise double slashes
Str::replaceAll( m_str , ss , s ) ;
// normalise funny characters
Str::replaceAll( m_str , "\t" , "" ) ;
Str::replaceAll( m_str , "\n" , "" ) ;
Str::replaceAll( m_str , "\r" , "" ) ;
// normalise case
if( !FileSystem::caseSensitive() )
Str::toLower(m_str) ;
// remove trailing slashes where appropriate
while( (
m_str.size() > 1U &&
m_str.at(m_str.size()-1) == FileSystem::slash() &&
!( FileSystem::usesDriveLetters() &&
m_str.size() == 3U &&
m_str.at(1) == ':' ) ) )
{
m_str.resize( m_str.size()-1U ) ;
}
// restore leading double slash
if( has_leading_double_slash )
m_str = s + m_str ;
// prepare a pointer to the extension
const char *slash = std::strrchr( m_str.c_str() , FileSystem::slash() ) ;
m_dot = std::strrchr( m_str.c_str() , '.' ) ;
if( m_dot != NULL && slash != NULL && m_dot < slash ) // ie. if "foo.bar/bletch"
m_dot = NULL ;
// make a copy of the extension
if( m_dot != NULL )
{
m_extension = std::string(m_dot+1U) ;
}
}
bool G::Path::valid() const
{
const char *slash = std::strrchr( m_str.c_str() , FileSystem::slash() ) ;
const char *dot = std::strrchr( m_str.c_str() , '.' ) ;
if( dot && slash && dot < slash )
dot = NULL ;
return m_dot == dot ;
}
const char *G::Path::pathCstr() const
{
validate("pathCstr") ;
return m_str.c_str() ;
}
std::string G::Path::str() const
{
validate("str") ;
return m_str ;
}
void G::Path::streamOut( std::ostream & stream ) const
{
stream << str() ;
}
void G::Path::validate( const char * where ) const
{
if( !valid() )
{
G_ERROR( "G::Path::validate: " << where << ": \"" << m_str << "\"" ) ;
G_ASSERT( !"invalid Path" ) ;
}
}
bool G::Path::simple() const
{
return dirname().str().empty() ;
}
bool G::Path::isRelative() const
{
return !isAbsolute() ;
}
bool G::Path::isAbsolute() const
{
if( hasNetworkDrive() )
return true ;
std::string str(m_str) ;
if( hasDriveLetter() )
str.erase( 0U , driveString().length() ) ;
return str.length() > 0U && str.at(0U) == FileSystem::slash() ;
}
void G::Path::setExtension( const std::string & extension )
{
bool dotted = extension.length() && extension.at(0U) == '.' ;
Path copy = *this ;
copy.removeExtension() ;
std::string s( copy.str() ) ;
s.append( 1U , '.' ) ;
s.append( dotted ? extension.substr(1U) : extension ) ;
set( s ) ;
validate( "setExtension" ) ;
}
std::string G::Path::basename() const
{
// for consistency compare m_str with dirname() and return the
// difference, excluding any leading slash
std::string result( m_str ) ;
std::string head( dirname().str() ) ;
if( head.length() == 0 )
{
}
else
{
result.erase( 0U , head.length() ) ;
if( result.at(0) == FileSystem::slash() )
result.erase(0U,1U) ;
}
return result ;
}
G::Path G::Path::dirname() const
{
validate("dirname") ;
std::string result ;
if( FileSystem::usesDriveLetters() &&
m_str.size() >= 2 && m_str.at(1) == ':' )
{
if( noSlash() )
{
if( m_str.size() > 2 )
result = driveString() ;
else
result = "" ;
}
else
{
if( m_str.rfind(FileSystem::slash()) == 2U )
{
if( m_str.size() == 3U )
{
result = "" ;
}
else
{
result = noTail() ;
if( result.length() == 2 )
result.append( slashString().c_str() ) ;
}
}
else
{
result = noTail() ;
}
}
}
else if( FileSystem::leadingDoubleSlash() &&
m_str.size() >= 2U &&
m_str.substr(0U,2U) == doubleSlashString() )
{
size_t slash_count = 0U ;
for( const char * p = m_str.c_str() ; *p ; p++ )
if( *p == FileSystem::slash() )
slash_count++ ;
if( slash_count > 3U )
result = noTail() ;
else
result = "" ;
}
else
{
if( noSlash() || m_str.size() == 1U )
{
result = "" ;
}
else
{
result = noTail() ;
if( result.length() == 0 )
result = slashString() ;
}
}
return Path(result) ;
}
std::string G::Path::noTail() const
{
G_ASSERT( !noSlash() ) ;
return m_str.substr( 0 , m_str.rfind(slashString()) ) ;
}
bool G::Path::noSlash() const
{
return m_str.find( slashString() ) == std::string::npos ;
}
size_t G::Path::slashAt() const
{
size_t position = m_str.find( slashString() ) ;
G_ASSERT( position != std::string::npos ) ;
return position ;
}
std::string G::Path::slashString()
{
return std::string ( 1U , FileSystem::slash() ) ;
}
std::string G::Path::doubleSlashString()
{
return std::string ( 2U , FileSystem::slash() ) ;
}
bool G::Path::hasDriveLetter() const
{
return
FileSystem::usesDriveLetters() &&
m_str.size() >= 2U &&
m_str.at(1U) == ':' ;
}
bool G::Path::hasNetworkDrive() const
{
return
FileSystem::leadingDoubleSlash() &&
m_str.size() > 2U&&
m_str.at(0U) == FileSystem::slash() &&
m_str.at(1U) == FileSystem::slash() ;
}
std::string G::Path::driveString() const
{
G_ASSERT( m_str.at(1U) == ':' ) ;
G_ASSERT( FileSystem::usesDriveLetters() ) ;
return std::string( 1U , m_str.at(0U) ) + std::string(":") ;
}
void G::Path::removeExtension()
{
if( m_dot != NULL )
{
m_str.resize( m_str.size() - std::strlen(m_dot) ) ;
m_dot = NULL ;
normalise() ; // in case of dir/foo.bar.bletch
}
validate("removeExtension") ;
}
void G::Path::setDirectory( const std::string & dir )
{
std::string temp( basename() ) ;
set( dir ) ;
pathAppend( temp ) ;
validate("setDirectory") ;
}
void G::Path::pathAppend( const std::string & tail )
{
// if empty or root or just a drive letter...
if( m_str.size() == 0U || m_str == slashString() ||
( hasDriveLetter() && m_str == driveString() ) )
{
; // no-op
}
else
{
m_str.append( slashString().c_str() ) ;
}
m_str.append( tail ) ;
normalise() ;
validate("pathAppend") ;
}
std::string G::Path::extension() const
{
return m_extension ;
}
G::Strings G::Path::split( bool no_dot ) const
{
Path path( *this ) ;
Strings list ;
for( unsigned int part = 0U ;; part++ )
{
std::string front = path.dirname().str() ;
std::string back = path.basename() ;
// if a dot in the middle or end of the path...
if( back == std::string(".") && no_dot && front.length() != 0U )
; // ...ignore it
else
list.push_front( back ) ;
if( front.length() == 0U )
break ;
path = Path(front) ;
}
return list ;
}
bool G::Path::operator==( const Path & other ) const
{
return m_str == other.m_str ;
}
G::Path &G::Path::operator=( const Path & other )
{
if( &other != this )
set( other.str() ) ;
return *this ;
}

179
src/glib/gpath.h Normal file
View File

@ -0,0 +1,179 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gpath.h
//
#ifndef G_PATH_H
#define G_PATH_H
#include "gdef.h"
#include "gstrings.h"
#include <string>
#include <iostream>
namespace G
{
class Path ;
} ;
// Class: G::Path
// Description: A Path object represents a file system
// path. The class is concerned with path syntax, not
// file system i/o. This class is necessary because
// of the mess Microsoft made with drive letters (like
// having a cwd associated with each drive).
// See also: File, Directory, FileSystem
//
class G::Path
{
public:
Path() ;
// Default constructor. Creates
// a zero-length path.
Path( const std::string & path ) ;
// Constructor.
Path( const char *path ) ;
// Constructor.
Path( const Path &other ) ;
// Copy constructor.
virtual ~Path() ;
// Virtual destructor.
bool simple() const ;
// Returns true if the path is just a
// file/directory name without
// any separators. Note that if the path
// is simple() then dirname() will
// return the empty string.
std::string str() const ;
// Returns the path string.
const char *pathCstr() const ;
// Returns the path string.
std::string basename() const ;
// Returns the path, excluding drive/directory parts.
// Does nothing with the extension (cf. basename(1)).
Path dirname() const ;
// Returns the drive/directory parts of the path. If
// this path is the top of the tree then the
// null path is returned.
//
// eg. c:foo\bar.exe -> c:foo
// eg. c:\foo\bar.exe -> c:\foo
// eg. c:bar.exe -> c:
// eg. c:\file -> c:\
// eg. c:\ -> <empty>
// eg. c: -> <empty>
// eg. \foo\bar.exe -> \foo
// eg. \ -> <empty>
// eg. foo\bar\bletch -> foo\bar
// eg. foo\bar -> foo
// eg. bar.exe -> <empty>
// eg. \\machine\drive\dir\file.cc -> \\machine\drive\dir
// eg. \\machine\drive\file -> \\machine\drive
// eg. \\machine\drive -> <empty>
std::string extension() const ;
// Returns the path's original extension, even
// after removeExtension(). Returns
// the zero-length string if there is none.
void removeExtension() ;
// Modifies the path by removing any extension.
// However, the extension returned by extension()
// is unchanged.
void setExtension( const std::string & extension ) ;
// Replaces the extension. Any leading dot in the
// given string is ignored. (The given extension
// will be returned by subsequent calls
// to extension().)
bool isAbsolute() const ;
// Returns !isRelative().
bool isRelative() const ;
// Returns true if the path is a relative
// path.
bool hasDriveLetter() const ;
// Returns true if the path has a leading
// drive letter (and the file-system
// uses drive letters).
Path & operator=( const Path &other ) ;
// Assignment operator.
void setDirectory( const std::string & dir ) ;
// Sets the drive/directory.
void pathAppend( const std::string & tail ) ;
// Appends a filename to the path. A path separator
// is added if necessary.
Strings split( bool no_dot = true ) const ;
// Spits the path into a list
// of component parts.
bool operator==( const Path & path ) const ;
// Comparison operator.
void streamOut( std::ostream & stream ) const ;
// Streams out the path.
private:
void set( const std::string & path ) ;
void normalise() ;
void clear() ;
void validate( const char * ) const ;
bool valid() const ;
static std::string slashString() ;
static std::string doubleSlashString() ;
std::string driveString() const ;
size_t slashAt() const ;
bool noSlash() const ;
std::string noTail() const ;
bool hasNetworkDrive() const ;
private:
std::string m_str ;
std::string m_extension ;
const char *m_dot ;
} ;
namespace G
{
inline
std::ostream & operator<<( std::ostream & stream , const Path & path )
{
path.streamOut( stream ) ;
return stream ;
}
} ;
#endif

77
src/glib/gpid.h Normal file
View File

@ -0,0 +1,77 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gpid.h
//
#ifndef G_PID_H
#define G_PID_H
#include "gdef.h"
#include <iostream>
namespace G
{
class PidImp ;
class Pid ;
} ;
// Class: G::Pid
// Description: A process-id class. Uses a pimple
// pattern to hide windows/unix type differences.
//
class G::Pid
{
public:
Pid() ;
// Default constructor for this
// process's id.
~Pid() ;
// Destructor.
Pid( const Pid & ) ;
// Copy constructor.
Pid & operator=( const Pid & ) ;
// Assignment operator.
std::string str() const ;
// Returns a string representation.
bool operator==( const Pid & ) const ;
// Comparison operator.
private:
PidImp * m_imp ;
} ;
namespace G
{
inline
std::ostream & operator<<( std::ostream & stream , const Pid & pid )
{
stream << pid.str() ;
return stream ;
}
} ;
#endif

81
src/glib/gpid_unix.cpp Normal file
View File

@ -0,0 +1,81 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gpid_unix.cpp
//
#include "gdef.h"
#include "gpid.h"
#include <unistd.h>
#include <sys/types.h>
#include <sstream>
namespace G
{
class PidImp ;
} ;
// Class: G::PidImp
// Description: A pimple implementation class for GPid.
//
class G::PidImp
{
public:
pid_t m_pid ;
} ;
// ===
G::Pid::Pid() : m_imp(NULL)
{
m_imp = new PidImp ;
m_imp->m_pid = ::getpid() ;
}
G::Pid::~Pid()
{
delete m_imp ;
}
G::Pid::Pid( const Pid & other ) :
m_imp(NULL)
{
m_imp = new PidImp ;
m_imp->m_pid = other.m_imp->m_pid ;
}
G::Pid & G::Pid::operator=( const Pid & rhs )
{
m_imp->m_pid = rhs.m_imp->m_pid ;
return *this ;
}
std::string G::Pid::str() const
{
std::stringstream ss ;
ss << m_imp->m_pid ;
return ss.str() ;
}
bool G::Pid::operator==( const Pid & rhs ) const
{
return m_imp->m_pid == rhs.m_imp->m_pid ;
}

79
src/glib/gpid_win32.cpp Normal file
View File

@ -0,0 +1,79 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gpid_win32.cpp
//
#include "gdef.h"
#include "gpid.h"
#include <process.h>
namespace G
{
class PidImp ;
} ;
// Class: G::PidImp
// Description: A pimple implementation class for GPid.
//
class G::PidImp
{
public:
int m_pid ;
} ;
// ===
G::Pid::Pid() : m_imp(NULL)
{
m_imp = new PidImp ;
m_imp->m_pid = ::_getpid() ;
}
G::Pid::~Pid()
{
delete m_imp ;
}
G::Pid::Pid( const Pid & other ) :
m_imp(NULL)
{
m_imp = new PidImp ;
m_imp->m_pid = other.m_imp->m_pid ;
}
G::Pid & G::Pid::operator=( const Pid & rhs )
{
m_imp->m_pid = rhs.m_imp->m_pid ;
return *this ;
}
std::string G::Pid::str() const
{
std::stringstream ss ;
ss << m_imp->m_pid ;
return ss.str() ;
}
bool G::Pid::operator==( const Pid & rhs ) const
{
return m_imp->m_pid == rhs.m_imp->m_pid ;
} ;

467
src/glib/gstr.cpp Normal file
View File

@ -0,0 +1,467 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gstr.cpp
//
#include "gdef.h"
#include "gstr.h"
#include "gdebug.h"
#include <cmath>
#include <ctype.h>
#include <iomanip>
#include <climits>
#include <string>
#include <sstream>
#include <xlocale>
bool G::Str::replace( std::string &s , const std::string &from ,
const std::string &to , size_t *pos_p )
{
if( from.length() == 0 )
return false ;
size_t pos = pos_p == NULL ? 0 : *pos_p ;
if( pos >= s.length() )
return false ;
pos = s.find( from , pos ) ;
if( pos == std::string::npos )
{
return false ;
}
else
{
s.replace( pos , from.length() , to ) ;
if( pos_p != NULL )
*pos_p = pos + to.length() ;
return true ;
}
}
size_t G::Str::replaceAll( std::string &s , const std::string &from ,
const std::string &to )
{
size_t count = 0U ;
for( size_t pos = 0U ; replace( s , from , to , &pos ) ; count++ )
; // no-op
return count ;
}
void G::Str::trimLeft( std::string & s , const std::string & ws )
{
size_t n = s.find_first_not_of( ws ) ;
if( n == std::string::npos )
s = std::string() ;
else if( n != 0U )
s.erase( 0U , n ) ;
}
void G::Str::trimRight( std::string & s , const std::string & ws )
{
size_t n = s.find_last_not_of( ws ) ;
if( n == std::string::npos )
s = std::string() ;
else if( n != 0U )
s.erase( n+1U , s.length()-n-1U ) ;
}
void G::Str::trim( std::string & s , const std::string & ws )
{
trimLeft(s,ws) ; trimRight(s,ws) ;
}
bool G::Str::isNumeric( const std::string & s , bool allow_minus_sign )
{
const char * p = s.c_str() ;
if( allow_minus_sign && *p == '-' )
p++ ;
for( ; *p ; p++ )
{
if( *p < '0' || *p > '9' )
return false ;
}
return true ;
}
bool G::Str::isPrintableAscii( const std::string & s )
{
for( const char * p = s.c_str() ; *p ; p++ )
{
if( *p < 0x20 || *p >= 0x7f )
return false ;
}
return true ;
}
bool G::Str::isUShort( const std::string & s )
{
try
{
(void) toUShort(s) ;
}
catch( Overflow & )
{
return false ;
}
catch( InvalidFormat & )
{
return false ;
}
return true ;
}
bool G::Str::isUInt( const std::string & s )
{
try
{
(void) toUInt(s) ;
}
catch( Overflow & )
{
return false ;
}
catch( InvalidFormat & )
{
return false ;
}
return true ;
}
bool G::Str::isULong( const std::string & s )
{
try
{
(void) toULong(s) ;
}
catch( Overflow & )
{
return false ;
}
catch( InvalidFormat & )
{
return false ;
}
return true ;
}
unsigned int G::Str::toUInt( const std::string &s , bool limited )
{
unsigned long ulong_val = toULong( s ) ;
unsigned int uint_val = static_cast<unsigned int>( ulong_val ) ;
if( uint_val != ulong_val )
{
if( limited )
uint_val = UINT_MAX ;
else
throw Overflow( s ) ;
}
return uint_val ;
}
unsigned long G::Str::toULong( const std::string &s , bool limited )
{
char * end = NULL ;
unsigned long result = ::strtoul( s.c_str(), &end, 0 ) ;
if( end == 0 || end[0] != '\0' )
throw InvalidFormat( s ) ;
if( result == ULONG_MAX )
{
if( limited )
result = ULONG_MAX ;
else
throw Overflow( s ) ;
}
return result ;
}
unsigned short G::Str::toUShort( const std::string &s , bool limited )
{
unsigned long ulong_val = toULong( s ) ;
unsigned short ushort_val = static_cast<unsigned short>( ulong_val ) ;
if( ushort_val != ulong_val )
{
if( limited )
ushort_val = USHRT_MAX ;
else
throw Overflow( s ) ;
}
return ushort_val ;
}
void G::Str::toLower( std::string &s )
{
for( std::string::iterator p = s.begin() ; p != s.end() ; ++p )
{
*p = ::tolower( *p ) ;
}
}
void G::Str::toUpper( std::string &s )
{
for( std::string::iterator p = s.begin() ; p != s.end() ; ++p )
{
*p = ::toupper( *p ) ;
}
}
std::string G::Str::toPrintableAscii( char c , char escape )
{
if( c == escape )
{
return std::string( 2U , c ) ;
}
else if( c >= 0x20 && c < 0x7f )
{
return std::string( 1U , c ) ;
}
std::string result( 1U , escape ) ;
if( c == '\n' )
{
result.append( 1U , 'n' ) ;
}
else if( c == '\t' )
{
result.append( 1U , 't' ) ;
}
else
{
unsigned int n = c ;
result.append( 1U , char('0'+((n/64U)%8U)) ) ;
result.append( 1U , char('0'+((n/8U)%8U)) ) ;
result.append( 1U , char('0'+(n%8U)) ) ;
}
return result ;
}
std::string G::Str::toPrintableAscii( const std::string & in , char escape )
{
std::string result ;
for( const char * p = in.c_str() ; *p ; ++p )
result.append( toPrintableAscii(*p,escape) ) ;
return result ;
}
std::string G::Str::readLineFrom( std::istream & stream , char ignore )
{
std::string line ;
char c ;
while( stream.get(c) ) // ie. while(stream.good())
{
if( c == '\n' )
break ;
if( ignore != '\0' && c == ignore )
;
else
line.append(1U,c) ;
}
return line ;
}
std::string G::Str::readLineFrom( std::istream & stream , const std::string & eol )
{
const size_t eol_length = eol.length() ;
std::string line ;
char c ;
for( size_t line_length = 1U ; stream.get(c) ; ++line_length )
{
line.append(1U,c) ;
if( line_length >= eol_length )
{
const size_t offset = line_length - eol_length ;
if( line.find(eol,offset) == offset )
{
line.erase(offset) ;
return line ;
}
}
}
return line ;
}
std::string G::Str::wrap( std::string text , const std::string & prefix_1 ,
const std::string & prefix_2 , size_t width )
{
std::string ws( " \t\n" ) ;
std::stringstream ss ;
for( bool first_line = true ; text.length() ; first_line = false )
{
const size_t prefix_length =
first_line ? prefix_1.length() : prefix_2.length() ;
size_t w = (width > prefix_length) ? (width-prefix_length) : width ;
const size_t pos_nl = text.find_first_of("\n") ;
if( pos_nl != std::string::npos && pos_nl != 0U && pos_nl < w )
{
w = pos_nl ;
}
std::string line = text ;
if( text.length() > w )
{
line = text.substr( 0U , w ) ;
if( text.find_first_of(ws,w) != w )
{
const size_t white_space = line.find_last_of( ws ) ;
const size_t black_space = line.find_first_not_of( ws ) ;
if( white_space != std::string::npos &&
black_space != std::string::npos &&
(white_space+1U) != black_space )
{
line = line.substr( 0U , white_space ) ;
}
}
}
if( line.length() != 0U )
{
ss << ( first_line ? prefix_1 : prefix_2 ) << line << std::endl ;
}
text = text.length() == line.length() ?
std::string() : text.substr(line.length()) ;
const size_t black_space = text.find_first_not_of( ws ) ;
if( black_space != 0U && black_space != std::string::npos )
{
size_t newlines = 0U ;
for( size_t pos = 0U ; pos < black_space ; ++pos )
{
if( text.at(pos) == '\n' )
{
newlines++ ;
if( newlines > 1U )
ss << prefix_2 << std::endl ;
}
}
text = text.substr( black_space ) ;
}
}
return ss.str() ;
}
void G::Str::listPushBack( void * out , const std::string & s )
{
reinterpret_cast<Strings*>(out)->push_back( s ) ;
}
void G::Str::arrayPushBack( void * out , const std::string & s )
{
reinterpret_cast<StringArray*>(out)->push_back( s ) ;
}
void G::Str::splitIntoTokens( const std::string &in , Strings &out ,
const std::string & ws )
{
splitIntoTokens( in , reinterpret_cast<void*>(&out) ,
&listPushBack , ws ) ;
}
void G::Str::splitIntoTokens( const std::string &in , StringArray &out ,
const std::string & ws )
{
splitIntoTokens( in , reinterpret_cast<void*>(&out) ,
&arrayPushBack , ws ) ;
}
void G::Str::splitIntoTokens( const std::string & in ,
void * out , void (*fn)(void*,const std::string&) ,
const std::string & ws )
{
for( size_t p = 0U ; p != std::string::npos ; )
{
p = in.find_first_not_of( ws , p ) ;
if( p != std::string::npos )
{
size_t end = in.find_first_of( ws , p ) ;
size_t len = end == std::string::npos ? end : (end-p) ;
(*fn)( out , in.substr( p , len ) ) ;
p = end ;
}
}
}
void G::Str::splitIntoFields( const std::string & in , Strings &out ,
const std::string & ws , char escape , bool discard_bogus )
{
splitIntoFields( in , reinterpret_cast<void*>(&out) ,
&listPushBack , ws , escape , discard_bogus ) ;
}
void G::Str::splitIntoFields( const std::string & in , StringArray &out ,
const std::string & ws , char escape , bool discard_bogus )
{
splitIntoFields( in , reinterpret_cast<void*>(&out) ,
&arrayPushBack , ws , escape , discard_bogus ) ;
}
void G::Str::splitIntoFields( const std::string & in_in , void * out ,
void (*fn)(void*,const std::string&) ,
const std::string & ws , char escape , bool discard_bogus )
{
std::string all( ws ) ;
if( escape != '\0' )
all.append( 1U , escape ) ;
if( in_in.length() )
{
std::string in = in_in ;
size_t start = 0U ;
size_t last_pos = in.length() - 1U ;
size_t pos = 0U ;
for(;;)
{
if( pos >= in.length() ) break ;
pos = in.find_first_of( all , pos ) ;
if( pos == std::string::npos ) break ;
if( in.at(pos) == escape )
{
const bool valid =
pos != last_pos &&
in.find(all,pos+1U) == (pos+1U) ;
if( valid || discard_bogus )
in.erase( pos , 1U ) ;
else
pos++ ;
pos++ ;
}
else
{
(*fn)( out , in.substr(start,pos-start) ) ;
pos++ ;
start = pos ;
}
}
(*fn)( out , in.substr(start,pos-start) ) ;
}
}

202
src/glib/gstr.h Normal file
View File

@ -0,0 +1,202 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gstr.h
//
#ifndef G_STR_H
#define G_STR_H
#include "gdef.h"
#include "gexception.h"
#include "gstrings.h"
#include <string>
#include <iostream>
#include <list>
#include <vector>
namespace G
{
class Str ;
} ;
// Class: G::Str
// Description: A static class which provides string helper functions.
//
class G::Str
{
public:
G_EXCEPTION( Overflow , "conversion error: over/underflow" ) ;
G_EXCEPTION( InvalidFormat, "conversion error: invalid format" ) ;
typedef std::vector<std::string GAllocator(std::string) > StringArray ;
static bool replace( std::string &s ,
const std::string &from , const std::string &to ,
size_t *pos_p = NULL ) ;
// Replaces 'from' with 'to', starting at offset '*pos_p'.
// Returns true if a substitution was made, and adjusts
// '*pos_p' by to.length().
static size_t replaceAll( std::string &s , const std::string &from ,
const std::string &to ) ;
// Does a global replace on string 's', replacing all
// occurences of sub-string 'from' with 'to'. Returns
// the number of substitutions made.
static void trimLeft( std::string & s , const std::string & ws ) ;
// Trims the lhs of s, taking off any of the 'ws' characters.
static void trimRight( std::string & s , const std::string & ws ) ;
// Trims the rhs of s, taking off any of the 'ws' characters.
static void trim( std::string & s , const std::string & ws ) ;
// Trims both ends of s, taking off any of the 'ws' characters.
static bool isNumeric( const std::string & s , bool allow_minus_sign = false ) ;
// Returns true if every character is a decimal digit.
// Empty strings return true.
static bool isPrintableAscii( const std::string & s ) ;
// Returns true if every character is a 7-bit, non-control
// character (ie. 0x20<=c<0x7f). Empty strings return true.
static bool isUShort( const std::string & s ) ;
// Returns true if the string can be converted into
// an unsigned short without throwing an exception.
static bool isUInt( const std::string & s ) ;
// Returns true if the string can be converted into
// an unsigned integer without throwing an exception.
static bool isULong( const std::string & s ) ;
// Returns true if the string can be converted into
// an unsigned long without throwing an exception.
static unsigned int toUInt( const std::string & s , bool limited = false ) ;
// Converts string 's' to an unsigned int.
//
// If 'limited' is true then very large numeric strings
// are limited to the maximum value of the numeric type,
// without an Overflow exception.
//
// Exception: Overflow
// Exception: InvalidFormat
static unsigned long toULong( const std::string &s , bool limited = false ) ;
// Converts string 's' to an unsigned long.
//
// If 'limited' is true then very large numeric strings
// are limited to the maximum value of the numeric type,
// without an Overflow exception.
//
// Exception: Overflow
// Exception: InvalidFormat
static unsigned short toUShort( const std::string &s , bool limited = false ) ;
// Converts string 's' to an unsigned short.
//
// If 'limited' is true then very large numeric strings
// are limited to the maximum value of the numeric type,
// without an Overflow exception.
//
// Exception: Overflow
// Exception: InvalidFormat
static void toUpper( std::string &s ) ;
// Replaces all lowercase characters in string 's' by
// uppercase characters.
static void toLower( std::string &s ) ;
// Replaces all uppercase characters in string 's' by
// lowercase characters.
static std::string toPrintableAscii( char c , char escape = '\\' ) ;
// Returns a printable, 7-bit-ascii string representing the given
// character. Typical return values include "\\", "\n",
// "\t", "\007", etc.
static std::string toPrintableAscii( const std::string & in , char escape = '\\' ) ;
// Returns a printable, 7-bit-ascii string representing the given input.
static std::string readLineFrom( std::istream &stream , char ignore = '\015' ) ;
// Reads a string from the given stream using newline as the
// terminator. The terminator is read from the stream
// but not put into the returned string.
//
// May return a partial line at the end of the stream.
//
// Any 'ignore' characters (control-m by default) read
// from the stream are discarded. An 'ignore'
// character of NUL ('\0') disables this feature.
static std::string readLineFrom( std::istream &stream , const std::string & eol ) ;
// An overload which uses 'eol' as the terminator, and
// without the 'ignore' feature.
static std::string wrap( std::string text ,
const std::string & prefix_first_line , const std::string & prefix_subsequent_lines ,
size_t width = 70U ) ;
// Does word-wrapping. The return value is a string with
// embedded newlines.
static void splitIntoTokens( const std::string & in , Strings &out ,
const std::string & ws ) ;
// Splits the string into 'ws'-delimited tokens. The
// behaviour is like ::strtok() in that adjacent delimiters
// count as one and leading and trailing delimiters are ignored.
// Ths output array is cleared first.
static void splitIntoTokens( const std::string & in , StringArray & out ,
const std::string & ws ) ;
// Overload for vector<string>.
static void splitIntoFields( const std::string & in , Strings &out ,
const std::string & seperators , char escape = '\0' ,
bool discard_bogus_escapes = true ) ;
// Splits the string into fields. Duplicated, leading
// and trailing separator characters are all significant.
// Ths output array is cleared first.
//
// If a non-null escape character is given then any escaped
// separator is not used for splitting. If the 'discard...'
// parameter is true then escapes will never appear in the
// output, except for where there were originally double escapes.
// This is the preferred behaviour but it can create problems
// if doing nested splitting -- the escapes are lost by the
// time the sub-strings are split.
static void splitIntoFields( const std::string & in , StringArray & out ,
const std::string & seperators , char escape = '\0' ,
bool discard_bogus_escapes = true ) ;
// Overload for vector<string>.
private:
static void listPushBack( void * , const std::string & ) ;
static void arrayPushBack( void * , const std::string & ) ;
static void splitIntoFields( const std::string & , void * ,
void (*fn)(void*,const std::string&) ,
const std::string & , char , bool ) ;
static void splitIntoTokens( const std::string & , void * ,
void (*fn)(void*,const std::string&) , const std::string & ) ;
Str() ; // not implemented
} ;
#endif

42
src/glib/gstrings.h Normal file
View File

@ -0,0 +1,42 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gstrings.h
//
#ifndef G_STRINGS_H
#define G_STRINGS_H
#include <string>
#include <list>
namespace G
{
// Typedef: Strings
// Description: A std::list of std::strings.
// See also: Str
//
typedef std::list<std::string GAllocator(std::string) > Strings ;
} ;
#endif

98
src/glib/gtime.cpp Normal file
View File

@ -0,0 +1,98 @@
//
// Copyright (C) 2001 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ===
//
// gtime.cpp
//
#include "gdef.h"
#include "gtime.h"
#include "gdatetime.h"
#include "gassert.h"
G::Time::Time( const G::DateTime::BrokenDownTime & tm )
{
m_hh = tm.tm_hour ;
m_mm = tm.tm_min ;
m_ss = tm.tm_sec ;
}
G::Time::Time()
{
G::DateTime::BrokenDownTime tm = G::DateTime::utc( G::DateTime::now() ) ;
m_hh = tm.tm_hour ;
m_mm = tm.tm_min ;
m_ss = tm.tm_sec ;
}
G::Time::Time( G::DateTime::EpochTime t )
{
G::DateTime::BrokenDownTime tm = G::DateTime::utc( t ) ;
m_hh = tm.tm_hour ;
m_mm = tm.tm_min ;
m_ss = tm.tm_sec ;
}
G::Time::Time( const LocalTime & )
{
G::DateTime::BrokenDownTime tm = G::DateTime::local( G::DateTime::now() ) ;
m_hh = tm.tm_hour ;
m_mm = tm.tm_min ;
m_ss = tm.tm_sec ;
}
G::Time::Time( G::DateTime::EpochTime t , const LocalTime & )
{
G::DateTime::BrokenDownTime tm = G::DateTime::local( t ) ;
m_hh = tm.tm_hour ;
m_mm = tm.tm_min ;
m_ss = tm.tm_sec ;
}
unsigned int G::Time::hours() const
{
return m_hh ;
}
unsigned int G::Time::minutes() const
{
return m_mm ;
}
unsigned int G::Time::seconds() const
{
return m_ss ;
}
std::string G::Time::hhmmss( const char * sep )
{
if( sep == NULL ) sep = "" ;
std::stringstream ss ;
ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) << sep << (m_ss/10U) << (m_ss%10U) ;
return ss.str() ;
}
std::string G::Time::hhmm( const char * sep )
{
if( sep == NULL ) sep = "" ;
std::stringstream ss ;
ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) ;
return ss.str() ;
}

Some files were not shown because too many files have changed in this diff Show More